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
  • 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

Contact Support

When contacting support, please include:

  1. Error messages (exact text)
  2. Console logs (if available)
  3. SDK version (1.0.0)
  4. Platform (React Native/React)
  5. Environment (Development/Production)
  6. 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.