{"record":{"id":"aac8afe09fc9ce16","repo":"aaif-goose/goose","slug":"goose-serve-started-with-tls-but-did-not-return-a","errorCode":null,"errorMessage":"goose serve started with TLS but did not return a certificate fingerprint","messagePattern":"goose serve started with TLS but did not return a certificate fingerprint","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ui/desktop/src/main.ts","lineNumber":1221,"sourceCode":"    let gooseServeResult: Awaited<ReturnType<typeof startGooseServe>>;\n    try {\n      gooseServeResult = await startGooseServe({\n        serverSecret,\n        dir: workingDir,\n        tls: true,\n        env: {\n          GOOSE_PATH_ROOT: appConfig.GOOSE_PATH_ROOT as string | undefined,\n        },\n        loginShellPath,\n        isPackaged: app.isPackaged,\n        resourcesPath: app.isPackaged ? process.resourcesPath : undefined,\n        logger: log,\n        diagnosticsDir: STARTUP_LOGS_DIR,\n        readinessFetch: net.fetch as unknown as typeof globalThis.fetch,\n      });\n      if (!gooseServeResult.certFingerprint) {\n        await gooseServeResult.cleanup();\n        throw new Error(\n          'goose serve started with TLS but did not return a certificate fingerprint'\n        );\n      }\n\n      const localCertFingerprint = normalizeFingerprint(gooseServeResult.certFingerprint);\n      if (\n        localCertificateTrust.trust.fingerprint &&\n        localCertificateTrust.trust.fingerprint !== localCertFingerprint\n      ) {\n        await gooseServeResult.cleanup();\n        throw new Error('goose serve TLS certificate fingerprint did not match readiness probe');\n      }\n      localCertificateTrust.trust.fingerprint = localCertFingerprint;\n    } catch (error) {\n      localCertificateTrust.release();\n      log.error('goose serve failed to start', error);\n      dialog.showMessageBoxSync({\n        type: 'error',","sourceCodeStart":1203,"sourceCodeEnd":1239,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/ui/desktop/src/main.ts#L1203-L1239","documentation":"After startGooseServe succeeds with TLS enabled, main.ts expects the result to carry certFingerprint (the serve process's self-signed cert pin). A missing fingerprint despite a TLS-enabled start means the version/format contract between the readiness probe (which captured a fingerprint) and the serve result diverged — the process is killed via cleanup() and app startup fails with a dialog.","triggerScenarios":"goose binary emits the fingerprint on a channel gooseServe.ts no longer parses (or vice versa after a downgrade); TLS handshake succeeded but fingerprint extraction from stdout/file returned nothing; mixed old binary + new desktop build.","commonSituations":"Partial updates where the desktop app updates but the bundled/native goose binary stays old (or GOOSE_BINARY points at a stale build); dev running against a locally built goose with changed output format; snapshot tests with a fake readinessFetch that never returns a fingerprint.","solutions":["Update the goose binary so its TLS fingerprint output matches the desktop app's parser (keep binary and app versions in lockstep)","If GOOSE_BINARY is set in dev, unset it or rebuild it from the same checkout","Check the startup diagnostics trace for fingerprint_wait events to see whether waitForFingerprint timed out vs never started","As a workaround, run without TLS locally so the fingerprint contract is skipped"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// main.ts already wraps this in try/catch with cleanup + dialog; callers should let it\n// propagate and rely on that handler:\ntry {\n  await startGooseServeFlow();\n} catch (e) {\n  if (e instanceof Error && e.message.includes('did not return a certificate fingerprint')) {\n    // binary/app version skew: update goose, don't retry loop\n  }\n  throw e;\n}","preventionTips":["Ship binary and desktop app as one versioned unit; reject mismatched pairs at startup","In dev, rebuild the goose binary whenever gooseServe.ts parsing changes","Assert certFingerprint presence in a smoke test for every release artifact"],"tags":["tls","certificates","version-skew","goose-serve","startup"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}