aaif-goose/goose · critical

GOOSE_SERVER__SECRET_KEY is required for goose serve

Error message

GOOSE_SERVER__SECRET_KEY is required for goose serve

What it means

Thrown by startGooseServe in the Electron main process when the serverSecret argument is empty after trimming. goose serve requires a shared bearer secret (GOOSE_SERVER__SECRET_KEY) to authenticate desktop<->backend traffic, so startup is aborted before the binary is even resolved. The error message is annotated with the path of a startup diagnostics trace that recorded a 'configuration_error' event.

Source

Thrown at ui/desktop/src/gooseServe.ts:344

  dir,
  serverSecret,
  tls = false,
  env: additionalEnv = {},
  loginShellPath,
  isPackaged,
  resourcesPath,
  logger = defaultLogger,
  diagnosticsDir,
  readinessFetch = fetch,
}: StartGooseServeOptions): Promise<GooseServeResult> => {
  const workingDir = dir || process.cwd();
  const startupTrace = createGooseServeStartupDiagnostics(diagnosticsDir, workingDir);
  const startupDiagnosticsPath = startupTrace?.diagnosticsPath ?? null;
  const secretKey = serverSecret.trim();
  if (!secretKey) {
    const message = 'GOOSE_SERVER__SECRET_KEY is required for goose serve';
    startupTrace?.record('configuration_error', { message });
    throw new Error(withStartupDiagnosticsPath(message, startupDiagnosticsPath));
  }

  let goosePath: string;
  try {
    goosePath = findGooseBinaryPath({ isPackaged, resourcesPath });
  } catch (error) {
    const message = errorMessage(error);
    startupTrace?.record('binary_resolve_error', { message });
    throw new Error(withStartupDiagnosticsPath(message, startupDiagnosticsPath));
  }

  const port = await findAvailablePort();
  const localServeScheme: LocalServeScheme = tls ? 'https' : 'http';
  const { httpBaseUrl, statusUrl, healthUrl, acpUrl, redactedAcpUrl } = buildLocalServeUrls(
    port,
    secretKey,
    localServeScheme
  );

View on GitHub (pinned to 3810898a74)

Solutions

  1. Pass a non-empty secret, e.g. generate one with crypto.randomBytes(32).toString('hex) before calling startGooseServe
  2. If you meant to reuse an external server's secret, export GOOSE_SERVER__SECRET_KEY in both processes and read it before the call
  3. Open the startup diagnostics file whose path is appended to the message to confirm the 'configuration_error' entry and inspect the other recorded steps

Example fix

// before
await startGooseServe({ serverSecret: process.env.GOOSE_SERVER__SECRET_KEY ?? '' });
// after
import { randomBytes } from 'crypto';
const secret = process.env.GOOSE_SERVER__SECRET_KEY || randomBytes(32).toString('hex');
await startGooseServe({ serverSecret: secret });
Defensive patterns

Strategy: validation

Validate before calling

import { randomBytes } from 'crypto';
const secret = process.env.GOOSE_SERVER__SECRET_KEY?.trim() || randomBytes(32).toString('hex');
if (!secret) throw new Error('bug: secret generation failed');
// safe to call:
await startGooseServe({ serverSecret: secret, /* ... */ });

Type guard

const hasServerSecret = (opts: StartGooseServeOptions): boolean =>
  typeof opts.serverSecret === 'string' && opts.serverSecret.trim().length > 0;

Try / catch

try {
  await startGooseServe({ serverSecret: secret });
} catch (e) {
  if (e instanceof Error && e.message.includes('GOOSE_SERVER__SECRET_KEY')) {
    // config problem: fix secret source, not a transient failure — do not retry blindly
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling startGooseServe({ serverSecret: '' }) or with a whitespace-only string; main.ts normally generates the secret, so this fires when a custom caller, test harness, or external-backend wiring passes an unset/empty value.

Common situations: Integrating gooseServe.ts into another entrypoint and forgetting to generate the secret; copying the external-backend flow but reading process.env.GOOSE_SERVER__SECRET_KEY before it is set; refactoring that renames the option and passes undefined (which then defaults to '').

Related errors


AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16). Data as JSON: /api/errors/f0145d7f588efc44. Report an issue: GitHub.