{"record":{"id":"391549a8a0e2d622","repo":"aaif-goose/goose","slug":"goose-server-secret-key-must-be-set-when-using-go","errorCode":null,"errorMessage":"GOOSE_SERVER__SECRET_KEY must be set when using GOOSE_EXTERNAL_BACKEND. Set it to the same value on both the server and the desktop client.","messagePattern":"GOOSE_SERVER__SECRET_KEY must be set when using GOOSE_EXTERNAL_BACKEND\\. Set it to the same value on both the server and the desktop client\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"ui/desktop/src/main.ts","lineNumber":929,"sourceCode":"  }\n\n  const configuredUrl = process.env.GOOSE_EXTERNAL_BACKEND_URL?.trim();\n  if (configuredUrl) {\n    return configuredUrl;\n  }\n\n  return `http://127.0.0.1:${process.env.GOOSE_PORT || '3000'}`;\n};\n\nconst getExternalBackendFromEnv = (): ExternalBackend | null => {\n  const url = getExternalBackendUrlFromEnv();\n  if (!url) {\n    return null;\n  }\n\n  const secret = process.env.GOOSE_SERVER__SECRET_KEY;\n  if (!secret) {\n    throw new Error(\n      'GOOSE_SERVER__SECRET_KEY must be set when using GOOSE_EXTERNAL_BACKEND. ' +\n        'Set it to the same value on both the server and the desktop client.'\n    );\n  }\n\n  return {\n    source: 'env',\n    url,\n    secret,\n  };\n};\n\nconst getServerSecret = (settings: Settings): string => {\n  if (settings.externalGoosed?.enabled && settings.externalGoosed.secret) {\n    return settings.externalGoosed.secret;\n  }\n  return GENERATED_SECRET;\n};","sourceCodeStart":911,"sourceCodeEnd":947,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/ui/desktop/src/main.ts#L911-L947","documentation":"At startup, main.ts reads GOOSE_EXTERNAL_BACKEND to point the desktop at an externally-run goose server instead of spawning one. That protocol requires a shared auth secret, so if GOOSE_EXTERNAL_BACKEND is set but GOOSE_SERVER__SECRET_KEY is empty, getExternalBackendFromEnv throws this immediately — it refuses an unauthenticated connection to a remote backend.","triggerScenarios":"Launching Goose Desktop with GOOSE_EXTERNAL_BACKEND=http://host:port but no GOOSE_SERVER__SECRET_KEY in the environment; secret set in the server's shell but not in the one launching Electron; typo in the variable name (e.g. GOOSE_SERVER_SECRET_KEY) so it reads undefined.","commonSituations":"Teams running goose serve centrally and connecting desktop clients; CI launching the app against a test backend; secret managed via dotenv file that isn't loaded because the app was started from Finder/Dock rather than a shell.","solutions":["Export GOOSE_SERVER__SECRET_KEY in the desktop client's environment with the exact same value the server was started with","Double-check spelling and dunder: GOOSE_SERVER__SECRET_KEY (two underscores between SERVER and SECRET_KEY)","If you did not intend an external backend, unset GOOSE_EXTERNAL_BACKEND so the app spawns its local backend and generates its own secret"],"exampleFix":"# before\nexport GOOSE_EXTERNAL_BACKEND=http://10.0.0.5:8000\nopen Goose.app  # throws\n# after (same value the server used)\nexport GOOSE_SERVER__SECRET_KEY=\"$SECRET\" \nexport GOOSE_EXTERNAL_BACKEND=http://10.0.0.5:8000\nopen Goose.app","handlingStrategy":"validation","validationCode":"// Run before app.whenReady():\nconst url = process.env.GOOSE_EXTERNAL_BACKEND;\nif (url && !process.env.GOOSE_SERVER__SECRET_KEY) {\n  throw new Error('GOOSE_EXTERNAL_BACKEND requires GOOSE_SERVER__SECRET_KEY');\n}","typeGuard":"const hasExternalBackendConfig = (): boolean =>\n  Boolean(process.env.GOOSE_EXTERNAL_BACKEND) &&\n  Boolean(process.env.GOOSE_SERVER__SECRET_KEY && process.env.GOOSE_SERVER__SECRET_KEY.length > 0);","tryCatchPattern":"try {\n  backend = getExternalBackendFromEnv();\n} catch (e) {\n  // config error: print the message and exit; do not fall back to local backend silently\n  dialog.showErrorBox('Configuration error', e instanceof Error ? e.message : String(e));\n  app.quit();\n}","preventionTips":["Document the env pair together; validate both at startup in one place","Use a dotenv file loaded explicitly by the launcher rather than inherited shell env","Add a smoke-test script that asserts env pairing before deploying clients"],"tags":["config","environment","secrets","external-backend","startup"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}