AlexxIT/go2rtc · error
session refresh failed after
Error message
session refresh failed after %d retries
What it means
The client received a 404 on a client-api URL whose error body references the configured hardware_id — meaning Ring no longer recognizes the session registered for this hardware ID. After clearing the session and retrying maxRetries times, every retry still got a session-related 404, so the client gives up. This indicates the hardware_id is not accepted by Ring's client API at all.
Solutions
- Generate a fresh random hardware_id in valid format and reinitialize the client
- Verify the hardware_id matches what your session creation actually registered
- Log in once with an official device to re-register, then reuse that hardware_id
- Check that clientAPIBaseURL is current — Ring sometimes changes API hosts
Example fix
// before
c := ring.NewClient(ring.WithHardwareID("")) // empty/invalid ID -> 404 loop
// after
hwID := strings.ToUpper(uuid.NewString())
c := ring.NewClient(ring.WithHardwareID(hwID)) Defensive patterns
Strategy: validation
Validate before calling
hwID := client.HardwareID()
if hwID == "" || len(hwID) < 16 {
return errors.New("hardware_id missing or malformed; regenerate before calling ring API")
} Type guard
func isSessionNotFound(err error) bool {
return err != nil && strings.Contains(err.Error(), "session refresh failed after")
} Try / catch
devices, err := client.GetDevices()
if isSessionNotFound(err) {
client.RegenerateHardwareID()
if err := client.EnsureSession(); err != nil {
return fmt.Errorf("hard failure, need full re-login: %w", err)
}
devices, err = client.GetDevices()
} Prevention
- Generate hardware_id as a proper random UUID at first run and persist it
- Avoid sharing one hardware_id across many clients
- Re-register the hardware_id if Ring purges sessions
- Pin to a maintained fork/version matching current Ring client-api base URL
When it happens
Trigger: Calling any Request() against clientAPIBaseURL endpoints (e.g. ring-doorbell APIs) where every response is 404 with an error string containing your hardware_id, even after session refresh retries are exhausted.
Common situations: Hardware ID generated in a wrong format or duplicated across clients, Ring server-side purged the session, using an old hardware_id that was deregistered, or regional Ring API rejecting unknown device IDs.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- failed to refresh session
- authentication failed while creating session
- session request failed with status
- multitrans: no session
- multitrans: talkback failed
AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07).
Data as JSON: /api/errors/1093e1b6c1669f79.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/ring/api.go:489
}
req.Header.Set("Authorization", "Bearer "+c.authToken.AccessToken)
continue
}
// Handle 404 error with hardware_id reference - session issue
if resp.StatusCode == 404 && strings.Contains(url, clientAPIBaseURL) {
var errorBody map[string]interface{}
if err := json.Unmarshal(responseBody, &errorBody); err == nil {
if errorStr, ok := errorBody["error"].(string); ok && strings.Contains(errorStr, c.hardwareID) {
// Session with hardware_id not found, refresh session
c.sessionMutex.Lock()
c.session = nil
c.sessionExpiry = time.Time{} // Reset session expiry
c.sessionMutex.Unlock()
if attempt == maxRetries {
return nil, fmt.Errorf("session refresh failed after %d retries", maxRetries)
}
if err := c.ensureSession(); err != nil {
return nil, fmt.Errorf("failed to refresh session: %w", err)
}
continue
}
}
}
// Handle other error status codes
if resp.StatusCode >= 400 {
return nil, fmt.Errorf("request failed with status %d: %s", resp.StatusCode, string(responseBody))
}
break
}View on GitHub (pinned to c245815e75)