{"record":{"id":"d984e3b1b051e5cc","repo":"calesthio/OpenMontage","slug":"service-account-credentials-did-not-yield-a-valid","errorCode":null,"errorMessage":"Service-account credentials did not yield a valid access token.","messagePattern":"Service-account credentials did not yield a valid access token\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"tools/google_credentials.py","lineNumber":135,"sourceCode":"    if not path or not os.path.exists(path):\n        raise RuntimeError(\n            \"GOOGLE_APPLICATION_CREDENTIALS is not set or points to a missing \"\n            \"file; cannot use service-account authentication.\"\n        )\n\n    try:\n        creds = service_account.Credentials.from_service_account_file(\n            path, scopes=scopes\n        )\n        creds.refresh(Request())\n    except Exception as exc:  # noqa: BLE001 - re-raised as actionable message\n        raise RuntimeError(\n            f\"Failed to load/refresh service-account credentials from {path}: {exc}\"\n        ) from exc\n\n    token = creds.token\n    if not token or not isinstance(token, str):\n        raise RuntimeError(\n            \"Service-account credentials did not yield a valid access token.\"\n        )\n\n    project_id = getattr(creds, \"project_id\", None)\n    ret_project_id = str(project_id) if project_id is not None else None\n    return token, ret_project_id\n","sourceCodeStart":117,"sourceCodeEnd":142,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/tools/google_credentials.py#L117-L142","documentation":"RuntimeError raised when a successful refresh leaves creds.token empty or non-string. It is a defensive guard after creds.refresh(Request()) — with well-formed google-auth versions the token is always populated, so hitting this usually indicates an unexpected credential subclass, an aborted refresh, or a google-auth version returning an odd token type.","triggerScenarios":"Extremely rare: a mocked/stubbed Credentials object in tests, a google-auth version regression, or custom credential classes where .token is not set post-refresh. Standard service-account flows practically never produce it.","commonSituations":"Unit tests monkeypatching google.oauth2.service_account.Credentials with fakes that skip token assignment; downgrading/pinning an unusual google-auth version.","solutions":["If in tests, make the fake Credentials set `token` to a string after refresh() is called.","Upgrade/pin google-auth to a current release (`pip install -U google-auth`) and retry.","If it persists with real keys, log type(creds) and creds.valid to confirm which credential class is in play and whether refresh actually succeeded.","Fall back to Application Default Credentials (gcloud auth application-default login) as an alternative auth path."],"exampleFix":"# before (test fake)\nclass FakeCreds:\n    def refresh(self, request): pass  # token never set -> RuntimeError\n\n# after\nclass FakeCreds:\n    def __init__(self):\n        self.token = \"fake-token\"  # str token present after refresh\n    def refresh(self, request): pass","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    token, project = get_service_account_token()\nexcept RuntimeError as e:\n    if \"did not yield a valid access token\" in str(e):\n        token, project = get_adc_token_fallback()  # Application Default Credentials path\n    else:\n        raise","preventionTips":["In tests, make credential fakes set a string token after refresh().","Pin a current google-auth version; audit after any auth-library upgrade.","Have an ADC fallback auth path for resilience."],"tags":["google","authentication","defensive-check","service-account"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}