{"record":{"id":"8dad2c986340abad","repo":"AlexxIT/go2rtc","slug":"failed-to-parse-refresh-token-w","errorCode":null,"errorMessage":"failed to parse refresh token: %w","messagePattern":"failed to parse refresh token: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/ring/api.go","lineNumber":198,"sourceCode":"\t\tif cachedClient.authToken != nil && time.Now().Before(cachedClient.tokenExpiry) {\n\t\t\tcachedClient.onTokenRefresh = onTokenRefresh\n\t\t\treturn cachedClient, nil\n\t\t}\n\t}\n\n\tclient := &RingApi{\n\t\thttpClient:     &http.Client{Timeout: defaultTimeout},\n\t\tonTokenRefresh: onTokenRefresh,\n\t\thardwareID:     generateHardwareID(),\n\t\tauth:           auth,\n\t\tcacheKey:       cacheKey,\n\t}\n\n\tswitch a := auth.(type) {\n\tcase RefreshTokenAuth:\n\t\tconfig, err := parseAuthConfig(a.RefreshToken)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse refresh token: %w\", err)\n\t\t}\n\n\t\tclient.authConfig = config\n\t\tclient.hardwareID = config.HID\n\t\tclient.RefreshToken = a.RefreshToken\n\t}\n\n\tclientCache[cacheKey] = client\n\n\treturn client, nil\n}\n\nfunc ClientAPI(path string) string {\n\treturn clientAPIBaseURL + path\n}\n\nfunc DeviceAPI(path string) string {\n\treturn deviceAPIBaseURL + path","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/pkg/ring/api.go#L180-L216","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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)."],"exampleFix":"// before\nclient, err := ring.NewClient(ring.RefreshTokenAuth{RefreshToken: strings.TrimSpace(yamlToken)}) // token was base64 of the real token\n// after\ntok, _ := base64.StdEncoding.DecodeString(yamlToken)\nclient, err := ring.NewClient(ring.RefreshTokenAuth{RefreshToken: string(tok)})","handlingStrategy":"try-catch","validationCode":"// sanity-check the token decodes before calling NewClient\nif _, err := parseAuthConfig(rt); err != nil { return fmt.Errorf(\"bad refresh token: %w\", err) }","typeGuard":null,"tryCatchPattern":"client, err := ring.NewClient(ring.RefreshTokenAuth{RefreshToken: rt})\nif err != nil {\n    var parseErr error\n    if errors.As(err, &parseErr) && strings.Contains(err.Error(), \"failed to parse refresh token\") {\n        return fmt.Errorf(\"regenerate the Ring refresh token via the auth flow: %w\", err)\n    }\n    return err\n}","preventionTips":["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)"],"tags":["go","ring","auth","token"],"backgroundTag":"invalid-argument-format","analyzedSha":"c245815e75e2a5fd60b4290f12bfc04e55a984d3","analyzedAt":"2026-09-07T11:47:02.965Z","contentChangedAt":"2026-09-07T11:47:02.965Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}