Runbook: token failures
OHIP access tokens come from POST {gateway}/oauth/v1/tokens, are cached per (tenant, environment) and refreshed before they
expire; the credentials are secret references resolved through the secret provider.
Symptoms
Section titled “Symptoms”- Invocations fail with 502
upstream_error,upstreamStatus401 (or 400) and the detail “Token request to ‘<environment>’ returned 401 (invalid_client: …)”; the invocation endsfailedwith error codeinvalid_clientand is dead-lettered (an authentication failure is permanent). - Logs:
Token request to … failed,Invalidated OHIP token for environment …, repeatedObtained OHIP token(a refresh loop). SecretNotFoundException(“Secret reference ‘…’ was not found by the ‘<provider>’ secret provider”) — the reference no longer resolves.- Right after rotating an app key / client secret in the secret store.
Diagnose
Section titled “Diagnose”- Which environment and since when:
GET /api/admin/invocations?tenantId=<id>&status=failed→errorCode/errorMessageof the newest rows; open one withGET /api/admin/invocations/{id}: the OHIP call it attempted is recorded with status 401 and a few milliseconds, and the error text names the token request (not the operation). - Logs of the host:
grep -E 'Token request|SecretNotFound|Invalidated OHIP token'(the failed invocation’s Warning line carries the token error). The environment is named, the secret value never is. - Is it the credential or the reference?
SecretNotFoundException→ the reference is wrong or the provider cannot read it (AWS: role/IRSA permissions; Vault: policy, token or Kubernetes role; env: the variable is missing or not under an allowed prefixOHIP_/STAYFN_SECRET_).- 401/400 from the token endpoint → the value is wrong or was rotated at Oracle but not in the store (or the reverse).
GET /api/admin/environments/{id}shows which references the environment uses (never values) and its OAuth flow.secret.rotatedrows inGET /api/admin/audit?tenantId=<id>&action=secret.rotatedtell whether StayFn already saw a new version.
Remediate
Section titled “Remediate”- Put the correct value in the secret store under the same reference (or
PUT /api/admin/environments/{id}to point at a new reference). - Apply it on every replica now instead of waiting for
Secrets:CacheTtl/Secrets:RotationCheckInterval(5 min each):POST /api/admin/environments/{id}/rotate-credentials(operator). It drops the cached values and the environment’s tokens on this replica, relays the same to the others throughpg_notify('secrets_rotated'), and writesenvironment.rotate. - Re-run a cheap call (
stayfn ohip ping --env <name> --hotel <code>from an operator machine, or one function invocation) and confirm a newObtained OHIP tokenlog line and a successful OHIP call. - Invocations that died meanwhile are dead letters — replay them once the token works (
dead-letter-storm.md).
WireMock’s token endpoint was switched to 401 invalid_client, a function was invoked (502, token failure in the invocation), the mapping was
restored, rotate-credentials was called and the next invocation succeeded.