{"record":{"id":"f64047c533502c00","repo":"nocobase/nocobase","slug":"oauth-device-sign-in-expired-run-nb-env-auth-o","errorCode":null,"errorMessage":"OAuth device sign-in expired. Run `nb env auth ${options.envName}` to try again.","messagePattern":"OAuth device sign-in expired\\. Run `nb env auth (.+?)` to try again\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/cli/src/lib/env-auth.ts","lineNumber":1106,"sourceCode":"    if (response.ok) {\n      if (!data || typeof data !== 'object' || typeof data.access_token !== 'string') {\n        throw new Error('OAuth token response is missing access_token.');\n      }\n      return data as OauthTokenResponse;\n    }\n\n    const oauthError = typeof data === 'object' && data ? String((data as { error?: unknown }).error || '') : '';\n    if (oauthError === 'authorization_pending') {\n      updateTask(`Waiting for you to approve device sign-in for \"${options.envName}\"...`);\n      continue;\n    }\n    if (oauthError === 'slow_down') {\n      intervalMs += 5_000;\n      updateTask(`OAuth server asked us to slow down. Polling again in ${Math.ceil(intervalMs / 1000)}s...`);\n      continue;\n    }\n    if (oauthError === 'expired_token') {\n      throw new Error(`OAuth device sign-in expired. Run \\`nb env auth ${options.envName}\\` to try again.`);\n    }\n    if (oauthError === 'access_denied') {\n      throw new Error('OAuth device sign-in was denied.');\n    }\n\n    throw new Error(formatOauthError('Failed to poll OAuth device authorization', data, response.status));\n  }\n\n  throw new Error(`OAuth device sign-in timed out. Run \\`nb env auth ${options.envName}\\` to try again.`);\n}\n\nasync function refreshOauthAccessToken(options: {\n  envName: string;\n  baseUrl: string;\n  auth: OauthAuthConfig;\n  scope?: AuthStoreOptions['scope'];\n}) {\n  if (!options.auth.refreshToken || !options.auth.clientId) {","sourceCodeStart":1088,"sourceCodeEnd":1124,"githubUrl":"https://github.com/nocobase/nocobase/blob/fa42722fefe44265490dff2c27d79e2882bce4fa/packages/core/cli/src/lib/env-auth.ts#L1088-L1124","documentation":"Thrown by pollDeviceToken when the token endpoint returns the OAuth error code `expired_token`, meaning the device_code issued at the start of device authorization has passed its server-defined lifetime before the user completed sign-in. The CLI stops polling immediately and tells the user to restart the flow, because the device code is no longer valid.","triggerScenarios":"POST to the token endpoint with grant_type=urn:ietf:params:oauth:grant-type:device_code returns {\"error\":\"expired_token\"} — i.e. the user did not approve the sign-in in the browser before the device code expired (typically 5-15 minutes).","commonSituations":"Developer opened the verification URL late or left the browser tab pending; slow_down backoff stretched polling past expiry; the CLI was left running while the user was away; a server configured with a very short device-code TTL.","solutions":["Run `nb env auth <envName>` again and complete the browser approval promptly.","Open the verification_uri as soon as it is printed and approve before the code expires.","If the server expires codes too quickly for your workflow, ask the admin to increase the device-code lifetime."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await cliEnvAuth(envName);\n} catch (err) {\n  if (String(err.message).includes('device sign-in expired')) {\n    // restart the flow and approve promptly this time\n    await cliEnvAuth(envName);\n  } else throw err;\n}","preventionTips":["Open the verification URL immediately when printed","Approve before the printed code expires (usually a few minutes)","Avoid leaving `nb env auth` idle in a terminal while doing other work"],"tags":["oauth","device-flow","token-expired","timeout"],"backgroundTag":"device-code-expired","analyzedSha":"fa42722fefe44265490dff2c27d79e2882bce4fa","analyzedAt":"2026-09-01T00:54:31.202Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}