AlexxIT/go2rtc · error
failed to parse refresh token
Error message
failed to parse refresh token: %w
What it means
For RefreshTokenAuth, the factory parses the refresh token (which encodes an auth config JSON, including hardware ID) via parseAuthConfig. If the token is malformed, corrupted, or not the expected format, the underlying parse error is wrapped with this message. The token is not just an opaque string — it must decode into a valid config.
Solutions
- Regenerate a fresh refresh token using the library's official auth flow and use it verbatim.
- Trim whitespace/newlines from the token before parsing.
- Inspect the wrapped inner error (%w) to see whether it's a base64/JSON failure and fix that encoding.
- Ensure you are not passing an access token or password where the refresh token belongs.
- Store the token in a way that preserves it exactly (plain env var, single-quoted secret).
Example fix
// before
client, err := ring.NewClient(ring.RefreshTokenAuth{RefreshToken: strings.TrimSpace(yamlToken)}) // token was base64 of the real token
// after
tok, _ := base64.StdEncoding.DecodeString(yamlToken)
client, err := ring.NewClient(ring.RefreshTokenAuth{RefreshToken: string(tok)}) Defensive patterns
Strategy: try-catch
Validate before calling
// sanity-check the token decodes before calling NewClient
if _, err := parseAuthConfig(rt); err != nil { return fmt.Errorf("bad refresh token: %w", err) } Try / catch
client, err := ring.NewClient(ring.RefreshTokenAuth{RefreshToken: rt})
if err != nil {
var parseErr error
if errors.As(err, &parseErr) && strings.Contains(err.Error(), "failed to parse refresh token") {
return fmt.Errorf("regenerate the Ring refresh token via the auth flow: %w", err)
}
return err
} Prevention
- Generate the refresh token with the library's official auth tool only
- Never hand-edit, re-encode, or line-wrap the token when storing it
- Trim whitespace/newlines introduced by copy-paste
- Re-run the auth flow after regenerating credentials in the Ring ecosystem
- Store tokens in plain single-line form (env var or single-quoted secret)
When it happens
Trigger: Passing a truncated/corrupted refresh token; passing some other secret (e.g. an OAuth access token or a password) in place of a Ring refresh token; a token that was hand-edited or line-wrapped when copied.
Common situations: Copy/paste damage (whitespace/newlines introduced); regenerating tokens in the Ring app invalidates old-format tokens; storing the token through a system that mangles it (YAML quoting, base64 double-encoding).
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- refresh token is required
- email and password are required
- invalid auth type
- ring: invalid refresh token encoding
- failed to initialize token
AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07).
Data as JSON: /api/errors/8dad2c986340abad.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/ring/api.go:198
if cachedClient.authToken != nil && time.Now().Before(cachedClient.tokenExpiry) {
cachedClient.onTokenRefresh = onTokenRefresh
return cachedClient, nil
}
}
client := &RingApi{
httpClient: &http.Client{Timeout: defaultTimeout},
onTokenRefresh: onTokenRefresh,
hardwareID: generateHardwareID(),
auth: auth,
cacheKey: cacheKey,
}
switch a := auth.(type) {
case RefreshTokenAuth:
config, err := parseAuthConfig(a.RefreshToken)
if err != nil {
return nil, fmt.Errorf("failed to parse refresh token: %w", err)
}
client.authConfig = config
client.hardwareID = config.HID
client.RefreshToken = a.RefreshToken
}
clientCache[cacheKey] = client
return client, nil
}
func ClientAPI(path string) string {
return clientAPIBaseURL + path
}
func DeviceAPI(path string) string {
return deviceAPIBaseURL + pathView on GitHub (pinned to c245815e75)