mastra-ai/mastra · error · Error

GitHub token refresh requires an active Factory sandbox work

Error message

GitHub token refresh requires an active Factory sandbox workspace.

What it means

injectGithubToken looks up a GithubTokenInjector registered in the RequestContext under GITHUB_TOKEN_INJECTOR_CONTEXT_KEY. That injector is only registered when the request runs inside an active Factory sandbox workspace, since token injection mutates live sandbox credentials. Running outside a sandbox (local dev, plain server context, tests) leaves the injector absent, so the code throws instead of silently dropping the token.

Source

Thrown at mastracode/factory/src/integrations/github/token-refresh.ts:29

  requestContext.set(GITHUB_TOKEN_INJECTOR_CONTEXT_KEY, injector);
}

/** Record which PAT kind the active sandbox was provisioned with, so token
 * refresh re-injects the same credential (review-board sandboxes keep the
 * reviewer token instead of being clobbered with the worker token). */
export function registerGithubPatKind(requestContext: RequestContext, kind: GithubPatKind): void {
  requestContext.set(GITHUB_PAT_KIND_CONTEXT_KEY, kind);
}

export function getRegisteredGithubPatKind(requestContext: RequestContext): GithubPatKind {
  const kind = requestContext.get(GITHUB_PAT_KIND_CONTEXT_KEY);
  return kind === 'reviewer' ? 'reviewer' : 'default';
}

export function injectGithubToken(requestContext: RequestContext, token: string): void {
  const injector = requestContext.get(GITHUB_TOKEN_INJECTOR_CONTEXT_KEY) as GithubTokenInjector | undefined;
  if (!injector) {
    throw new Error('GitHub token refresh requires an active Factory sandbox workspace.');
  }
  injector(token);
}

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Run the token refresh inside an active Factory sandbox workspace so the injector is registered in the RequestContext
  2. Ensure the sandbox bootstrap (workspace provisioning) executes before any GitHub subscription tool can call refreshGithubToken
  3. In tests/local dev, register a stub GithubTokenInjector in the RequestContext under GITHUB_TOKEN_INJECTOR_CONTEXT_KEY
  4. Guard the call site: skip refreshGithubToken when the injector is absent and log instead of throwing

Example fix

// before
requestContext.set('github-token-injector', undefined);
await refreshGithubToken(requestContext, github); // throws
// after
requestContext.set(GITHUB_TOKEN_INJECTOR_CONTEXT_KEY, (token: string) => {
  sandboxCredentials.setGithubToken(token);
});
await refreshGithubToken(requestContext, github);
Defensive patterns

Strategy: type-guard

Validate before calling

const injector = requestContext.get(GITHUB_TOKEN_INJECTOR_CONTEXT_KEY) as GithubTokenInjector | undefined;
if (typeof injector !== 'function') {
  throw new Error('Token refresh skipped: no Factory sandbox workspace active.');
}

Type guard

function hasGithubTokenInjector(requestContext: RequestContext): boolean {
  return typeof requestContext.get(GITHUB_TOKEN_INJECTOR_CONTEXT_KEY) === 'function';
}

Try / catch

try {
  await injectGithubToken(requestContext, token);
} catch (err) {
  if ((err as Error).message.includes('active Factory sandbox workspace')) {
    logger.warn('Token injection skipped outside sandbox workspace');
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling injectGithubToken (typically from refreshGithubToken, which is invoked by the GitHub subscription tools) with a RequestContext that has no GithubTokenInjector bound — i.e. no Factory sandbox workspace is active for that request context.

Common situations: Running GitHub subscription tooling locally outside the Factory sandbox; tests that build a bare new RequestContext() without sandbox wiring; a refactor renamed or removed the sandbox bootstrap that registers the injector; the token refresh runs after the sandbox was torn down.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/7fcf74066083bd56. Report an issue: GitHub.