{"record":{"id":"12a30b51f3bd1715","repo":"windmill-labs/windmill","slug":"unknown-error","errorCode":"UNKNOWN_ERROR","errorMessage":"No JWT token received from server","messagePattern":"No JWT token received from server","errorType":"error_code","errorClass":"GitHubAppError","httpStatus":null,"severity":"error","filePath":"frontend/src/lib/githubApp.ts","lineNumber":333,"sourceCode":"\tcurrentWorkspace: string,\n\tinstallationId: number\n): Promise<void> {\n\t// Input validation\n\tif (!currentWorkspace) {\n\t\tthrow createGitHubAppError('Workspace is required', 'VALIDATION_ERROR')\n\t}\n\tif (!installationId || installationId <= 0) {\n\t\tthrow createGitHubAppError('Valid installation ID is required', 'VALIDATION_ERROR')\n\t}\n\n\ttry {\n\t\tconst response = await GitSyncService.exportInstallation({\n\t\t\tworkspace: currentWorkspace,\n\t\t\tinstallationId: installationId\n\t\t})\n\n\t\tif (!response.jwt_token) {\n\t\t\tthrow createGitHubAppError('No JWT token received from server', 'UNKNOWN_ERROR')\n\t\t}\n\n\t\tconst jwtToken = response.jwt_token\n\n\t\t// Copy to clipboard with fallback for unsecure contexts\n\t\tif (navigator.clipboard && navigator.clipboard.writeText) {\n\t\t\tawait navigator.clipboard.writeText(jwtToken)\n\t\t\tsendUserToast(\n\t\t\t\t'JWT token copied to clipboard. This token is sensitive and should be kept secret!',\n\t\t\t\tfalse,\n\t\t\t\tundefined,\n\t\t\t\tundefined,\n\t\t\t\t10000\n\t\t\t)\n\t\t} else {\n\t\t\t// Fallback: show the token in the toast for manual copying\n\t\t\tsendUserToast(\n\t\t\t\t`JWT token (copy manually): ${jwtToken}`,","sourceCodeStart":315,"sourceCodeEnd":351,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/githubApp.ts#L315-L351","documentation":"After GitSyncService.exportInstallation() returns, exportInstallation() checks that the server response contains a jwt_token field and throws this UNKNOWN_ERROR if it is missing/empty. It guards against a server or proxy responding 2xx with an unexpected body, before the token is copied to the clipboard.","triggerScenarios":"The backend endpoint for git_sync app installation export returns 200 but with a body lacking jwt_token — e.g. an API version mismatch where the field was renamed, an HTML error page served by a reverse proxy with status 200, or the server serializing an empty object.","commonSituations":"Frontend and backend deployed at mismatched versions (field renamed/removed); a dev proxy intercepting the request; the instance behind an auth gateway that rewrites responses; backend bug returning success without generating the token.","solutions":["Verify frontend and backend versions match and the git_sync export endpoint returns { jwt_token: ... }.","Inspect the raw HTTP response (network tab) to see what the server actually returned.","Check for a reverse proxy or gateway altering the response body/status.","Log out / re-login to rule out a stale session producing a degraded response."],"exampleFix":"// before\nconst response = await GitSyncService.exportInstallation({ workspace, installationId })\ncopyToClipboard(response.jwt_token)\n// after\nconst response = await GitSyncService.exportInstallation({ workspace, installationId })\nif (!response?.jwt_token) throw new Error('Server returned no jwt_token')\ncopyToClipboard(response.jwt_token)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function hasJwtToken(r: unknown): r is { jwt_token: string } {\n  return typeof r === 'object' && r !== null && typeof (r as any).jwt_token === 'string' && (r as any).jwt_token.length > 0\n}","tryCatchPattern":"try {\n  await exportInstallation(workspace, installationId)\n} catch (e) {\n  if (e?.message?.includes('No JWT token')) {\n    toast.error('Server did not return a token — check frontend/backend versions and proxy')\n  } else throw e\n}","preventionTips":["Keep frontend and backend versions in sync.","Add an API response schema check (zod) for exportInstallation responses.","Watch for reverse proxies rewriting JSON bodies in dev/test environments."],"tags":["api-response","jwt","github-app","server"],"backgroundTag":"api-response-missing-field","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}