Troubleshooting
Common issues and solutions for VOTR integration
Common Issues and Solutions
Installation Issues
Issue: “Module not found” error after SDK installation
Solution:
# Clear npm cache and reinstall
npm cache clean --force
rm -rf node_modules package-lock.json
npm install
npm install ./votr-vote-sdk-1.0.0.tgz --legacy-peer-deps
Issue: Peer dependency warnings
Solution:
The --legacy-peer-deps flag is required for this package. This is normal and expected.
Issue: TypeScript errors
Solution:
The SDK includes its own TypeScript definitions. If you’re still getting errors, try:
npm install @types/react @types/react-native --save-dev
Authentication Issues
Issue: “Invalid client credentials” error
Symptoms:
- OAuth API returns 401 or 403 error
- Authentication fails
Solution:
- Verify your Client ID and Client Secret are correct
- Ensure there are no extra spaces or characters
- Check that credentials are stored securely in your backend
- Contact Votr team to verify credentials
- Verify you’re using the correct environment URL
Issue: Token expiration errors
Symptoms:
- API calls work initially but fail after an hour
- “Token expired” error messages
Solution:
OAuth tokens expire after 1 hour. Implement token caching and refresh:
// Cache tokens with expiration
const getValidToken = async () => {
const now = Date.now()
if (cachedToken && cachedToken.expires > now) {
return cachedToken.access_token
}
// Token expired or doesn't exist, get new one
const newToken = await getOAuthToken()
cachedToken = {
access_token: newToken.access_token,
expires: now + newToken.expires_in * 1000,
}
return cachedToken.access_token
}
API Issues
Issue: “Shareholder not found” error
Symptoms:
- User exists but API returns “shareholder not found”
- Voting URL generation fails
Solution:
- Verify the email address is registered for the event
- Check that the eventId is correct and formatted properly
- Ensure the voting period is active
- Contact event administrator to verify user registration
Issue: Network request failing
Symptoms:
- API calls timeout or fail
- Connection errors
Solution:
- Check internet connection
- Verify API endpoints are correct:
- Development:
https://api-dev.govotr.com - Production:
https://api.govotr.com
- Development:
- Ensure proper headers are included
- Implement retry logic for network failures
const fetchWithRetry = async (url: string, options: any, retries = 3) => {
for (let i = 0; i < retries; i++) {
try {
const response = await fetch(url, options)
return response
} catch (error) {
if (i === retries - 1) throw error
await new Promise((resolve) => setTimeout(resolve, 1000 * (i + 1)))
}
}
}
SDK Component Issues
Issue: WebView not opening or blank screen
Symptoms:
- Button press doesn’t open voting interface
- Blank white screen appears
- Modal opens but no content
Solution:
- Check that the voting URL is valid and not empty
- Verify the URL format is correct (should contain JWT token)
- Test with a known working URL
- Check console for JavaScript errors
- Ensure WebView has proper permissions in your app
// Debug voting URL
console.log("Voting URL:", votingUrl)
console.log("URL is valid:", votingUrl && votingUrl.length > 0)
Issue: Button not responding to press
Symptoms:
- Button appears but doesn’t respond to taps
- No console logs from onPress handler
Solution:
- Check if button is disabled:
isDisabled={false} - Verify onPress function is defined
- Check for any overlapping views that might intercept touches
- Ensure button has proper dimensions and isn’t hidden
<VoteNowButton
URL={votingUrl}
isDisabled={false} // Explicitly set to false
onPress={() => console.log("Button pressed")} // Add for debugging
buttonStyle=
/>
Issue: Modal/WebView crashes or freezes
Symptoms:
- App crashes when voting modal opens
- WebView becomes unresponsive
- Memory issues during voting
Solution:
- Implement proper cleanup in component unmount
- Add error boundaries around the SDK component
- Monitor memory usage during development
useEffect(() => {
return () => {
// Cleanup when component unmounts
setVotingUrl("")
}
}, [])
Error Handling Patterns
SDK Error Types
<VoteNowButton
URL={votingUrl}
onError={(error) => {
console.error("SDK Error:", error)
let userMessage = "An unexpected error occurred during voting."
if (error.includes("network")) {
userMessage =
"Network connection lost. Please check your internet connection."
} else if (error.includes("timeout")) {
userMessage = "Voting session timed out. Please try again."
} else if (error.includes("permission")) {
userMessage = "You do not have permission to access this voting session."
} else if (error.includes("invalid_token")) {
userMessage = "Your voting session has expired. Please try again."
} else if (error.includes("already_voted")) {
userMessage = "You have already submitted your vote for this event."
}
Alert.alert("Voting Error", userMessage)
setVotingUrl("") // Clear URL to close modal
}}
/>
API Error Handling
const handleApiError = (error: any, context: string) => {
console.error(`${context} error:`, error)
if (error.response) {
// Server responded with error status
const status = error.response.status
const message = error.response.data?.message || "Unknown error"
switch (status) {
case 401:
return "Authentication failed. Please check your credentials."
case 403:
return "You don't have permission to perform this action."
case 404:
return "The requested resource was not found."
case 500:
return "Server error. Please try again later."
default:
return `Error ${status}: ${message}`
}
} else if (error.request) {
// Request was made but no response received
return "Network error. Please check your internet connection."
} else {
// Something else happened
return `Unexpected error: ${error.message}`
}
}
Performance Tips
1. Token Caching
Cache OAuth tokens to avoid unnecessary API calls:
const tokenCache = {
token: null,
expires: 0,
}
const getCachedToken = async () => {
if (tokenCache.token && Date.now() < tokenCache.expires) {
return tokenCache.token
}
const response = await getOAuthToken()
tokenCache.token = response.access_token
tokenCache.expires = Date.now() + response.expires_in * 1000
return tokenCache.token
}
2. Preload Voting URLs
Generate voting URLs when possible to reduce wait time:
useEffect(() => {
if (userEmail && eventId && !votingUrl) {
generateVotingUrl(userEmail, eventId)
}
}, [userEmail, eventId])
3. Loading States
Always show loading indicators for better UX:
const [isLoading, setIsLoading] = useState(false)
<VoteNowButton
URL={votingUrl}
isDisabled={isLoading || !votingUrl}
label={isLoading ? "Loading..." : "Vote Now"}
/>
4. Memory Management
Implement proper cleanup to prevent memory leaks:
useEffect(() => {
return () => {
// Cleanup when component unmounts
setVotingUrl("")
tokenCache.token = null
}
}, [])
Getting Additional Help
Development Resources
- 📋 Complete Examples: GitHub Repository
- 🔄 API Reference: API Documentation
- 📦 Installation Guide: Installation Instructions
Contact Support
When contacting support, please include:
- Error messages (exact text)
- Console logs (if available)
- SDK version (
1.0.0) - Platform (React Native/React)
- Environment (Development/Production)
- Steps to reproduce the issue
Debug Checklist
Before reporting issues, verify:
- SDK is installed correctly
- Client credentials are valid
- API endpoints are correct for your environment
- Network connectivity is working
- Voting URL is properly formatted
- Event is active and user is registered
- Console shows no JavaScript errors
- Button is not disabled
- Proper error handling is implemented
That’s it! If you’re still experiencing issues after following this troubleshooting guide, please contact the VOTR team with your specific error details and logs.