{"record":{"id":"7c468d08a785c068","repo":"lfnovo/open-notebook","slug":"failed-to-list-credentials","errorCode":null,"errorMessage":"Failed to list credentials","messagePattern":"Failed to list credentials","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"api/routers/credentials.py","lineNumber":139,"sourceCode":"        if provider:\n            credentials = await Credential.get_by_provider(provider)\n        else:\n            credentials = await Credential.get_all(order_by=\"provider, created\")\n\n        result = []\n        for cred in credentials:\n            models = await cred.get_linked_models()\n            result.append(credential_to_response(cred, len(models)))\n\n        return result\n\n    except HTTPException:\n        raise\n    except OpenNotebookError:\n        raise\n    except Exception as e:\n        logger.error(f\"Error listing credentials: {e}\")\n        raise HTTPException(status_code=500, detail=\"Failed to list credentials\")\n\n\n@router.get(\"/by-provider/{provider}\", response_model=List[CredentialResponse])\nasync def list_credentials_by_provider(provider: str):\n    \"\"\"List all credentials for a specific provider.\"\"\"\n    try:\n        credentials = await Credential.get_by_provider(provider.lower())\n        result = []\n        for cred in credentials:\n            models = await cred.get_linked_models()\n            result.append(credential_to_response(cred, len(models)))\n        return result\n    except HTTPException:\n        raise\n    except OpenNotebookError:\n        raise\n    except Exception as e:\n        logger.error(f\"Error listing credentials for {provider}: {e}\")","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/lfnovo/open-notebook/blob/a7de90d38aaf18ee85fd661854d35c11e44613e2/api/routers/credentials.py#L121-L157","documentation":"Catch-all 500 from the credential list endpoint (GET /api/credentials). It fires when listing credentials raises an exception that is neither HTTPException nor an OpenNotebookError — typically a database-level failure during the await db query.","triggerScenarios":"GET /api/credentials when SurrealDB is down or returns an unexpected error, or when a stored credential row cannot be deserialized into the Credential domain model (corrupt/legacy record).","commonSituations":"SurrealDB container stopped or restarting, records written by an older schema version, or permissions/connection config mismatch after an env change.","solutions":["Read the API log line 'Error listing credentials: ...' to identify the underlying exception","Ensure the database tier is up: make database, then make status","If a specific record fails to deserialize, inspect/remove the offending credential record via a DB query","Restart the API so automatic schema migrations run, then retry"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const creds = await api.listCredentials();\n} catch (e) {\n  if (e.status === 500) { showEmptyStateWithRetry(); return; }\n  throw e;\n}","preventionTips":["Cache the last successful credential list to keep the UI usable during DB blips","Health-check the DB before batch operations that list credentials"],"tags":["credentials","list","http-500","database"],"backgroundTag":"http-500-fallback","analyzedSha":"a7de90d38aaf18ee85fd661854d35c11e44613e2","analyzedAt":"2026-08-27T02:39:58.166Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}