{"record":{"id":"97f0cb74c12eb1da","repo":"mastra-ai/mastra","slug":"the-active-sandbox-provider-does-not-support-runti","errorCode":null,"errorMessage":"The active sandbox provider does not support runtime GitHub token refresh.","messagePattern":"The active sandbox provider does not support runtime GitHub token refresh\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/factory/src/workspace.ts","lineNumber":350,"sourceCode":"      }\n      const target: SessionSandbox = requireExec(args.sandbox);\n      // The `gh` CLI needs a PAT when the org configured one (installation\n      // tokens 403 on integration-restricted endpoints); git clone/checkout\n      // keep using the minted installation token. Resolved per start so the\n      // installed credential never outlives rotation.\n      const patKind = await resolveGithubPatKind('default');\n      const ghCliToken =\n        (await getGithubPat(() => github.integrationStorage, session.orgId, patKind)) ?? (await getRepositoryToken());\n      target.setEnv?.(env => ({ ...env, GH_TOKEN: ghCliToken }));\n      // Observability only — nothing reads these columns for decisions. The\n      // workdir was resolved (and memoized on the entry) by the guarded setup.\n      void storage.sessions\n        .setSandbox({ id: session.id, sandboxId: target.id, sandboxWorkdir: sessionEntry.workdir ?? '' })\n        .catch(() => {});\n      const tokenRegistration: GithubTokenRegistration = {\n        inject: freshToken => {\n          if (!target.setEnv) {\n            throw new Error('The active sandbox provider does not support runtime GitHub token refresh.');\n          }\n          target.setEnv(env => ({ ...env, GH_TOKEN: freshToken }));\n          tokenRegistration.ghToken = freshToken;\n        },\n        patKind,\n        ghToken: ghCliToken,\n        generation: 0,\n        tokenReplacementPending: false,\n      };\n      githubTokenInjectors.set(workspaceId, tokenRegistration);\n      registerGithubTokenContext(tokenRegistration);\n      // Project skill roots were reported empty by the unmaterialized-source\n      // guard before the checkout existed; rescan now. Fire-and-forget.\n      void constructedWorkspaces\n        .get(workspaceId)\n        ?.skills?.refresh()\n        .catch(() => {});\n    };","sourceCodeStart":332,"sourceCodeEnd":368,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory/src/workspace.ts#L332-L368","documentation":"The GithubTokenRegistration.inject callback needs to swap the sandbox's GH_TOKEN at runtime when the GitHub CLI token is refreshed. If the resolved sandbox provider instance does not implement setEnv, setupHook throws because token refresh is impossible with that provider.","triggerScenarios":"Starting a Factory session whose materialization pipeline calls inject() (token refresh) while the configured sandbox provider returns an instance lacking setEnv — i.e. a provider that only supports static env configuration.","commonSituations":"Switching to a minimal/custom sandbox provider that doesn't implement the full sandbox contract, running with a local or alternative provider in dev, or a version change where setEnv was added to the provider interface but the provider wasn't updated.","solutions":["Use a sandbox provider whose instances implement setEnv (support runtime env mutation)","Update your custom sandbox adapter to implement setEnv(fn) that applies env updates to the running sandbox","If runtime refresh isn't needed, provide a long-lived token (PAT) so inject() is never invoked","Check the provider version and upgrade to one matching the sandbox contract expected by workspace.ts"],"exampleFix":"// before\nconst sandbox = { start: async () => {}, exec: async () => {} }; // no setEnv\n// after\nconst sandbox = {\n  start: async () => {},\n  exec: async () => {},\n  setEnv(update) { this.env = update(this.env ?? {}); },\n};","handlingStrategy":"validation","validationCode":"const instance = await resolveSandbox(config);\nif (typeof instance.setEnv !== 'function') {\n  throw new Error('Sandbox provider must implement setEnv for GitHub token refresh');\n}","typeGuard":"function supportsRuntimeEnv(s) {\n  return typeof s === 'object' && s !== null && typeof s.setEnv === 'function';\n}","tryCatchPattern":"try {\n  await startFactorySession(sessionEntry);\n} catch (e) {\n  if (e.message.includes('runtime GitHub token refresh')) {\n    // swap to a setEnv-capable provider or use a long-lived PAT\n  } else throw e;\n}","preventionTips":["Assert the sandbox provider implements setEnv at startup (fail fast)","Prefer long-lived PATs when using minimal providers that cannot refresh tokens","Keep custom sandbox adapters in sync with the provider interface version"],"tags":["sandbox","github","token","capability-missing"],"backgroundTag":"unsupported-sandbox-provider-capability","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}