{"record":{"id":"1231b2112aedd0d6","repo":"windmill-labs/windmill","slug":"validation-error","errorCode":"VALIDATION_ERROR","errorMessage":"VALIDATION_ERROR | NETWORK_ERROR | AUTH_ERROR | UNKNOWN_ERROR","messagePattern":"VALIDATION_ERROR \\| NETWORK_ERROR \\| AUTH_ERROR \\| UNKNOWN_ERROR","errorType":"error_code","errorClass":"GitHubAppError","httpStatus":null,"severity":"warning","filePath":"frontend/src/lib/githubApp.ts","lineNumber":34,"sourceCode":"\t * workspace), and matching on the org name resolves to the wrong one.\n\t */\n\tselectedGHAppInstallationId: number | undefined\n\tselectedGHAppRepository: string | undefined\n\tgithubInstallationUrl: string | undefined\n\tinstallationCheckInterval: number | undefined\n\tisCheckingInstallation: boolean\n\timportJwt: string\n\t/**\n\t * True when the instance has a self-managed (GHES) GitHub App configured.\n\t * Used to hide cloud-only UI like the Export/Import buttons, since those\n\t * JWTs carry no `github_base_url` and would round-trip into broken\n\t * github.com-pointed installs.\n\t */\n\tisGhesSelfManaged: boolean\n}\n\nexport interface GitHubAppError extends Error {\n\tcode: 'VALIDATION_ERROR' | 'NETWORK_ERROR' | 'AUTH_ERROR' | 'UNKNOWN_ERROR'\n\tdetails?: unknown\n}\n\n/**\n * Creates a standardized GitHub App error\n */\nfunction createGitHubAppError(\n\tmessage: string,\n\tcode: GitHubAppError['code'],\n\tdetails?: unknown\n): GitHubAppError {\n\tconst error = new Error(message) as GitHubAppError\n\terror.code = code\n\terror.details = details\n\treturn error\n}\n\n/**","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/githubApp.ts#L16-L52","documentation":"GitHubAppError is the standardized error type created by frontend/src/lib/githubApp.ts for all GitHub App related failures. Its `code` field classifies the failure: VALIDATION_ERROR (bad input like empty slug/installation id), NETWORK_ERROR (fetch failures), AUTH_ERROR (token/jwt problems), UNKNOWN_ERROR (anything else). The example shows code=VALIDATION_ERROR, thrown when inputs fail validation before any network call is made.","triggerScenarios":"Calling a githubApp.ts helper (e.g. buildInstallationUrl or similar) with invalid arguments — an empty or malformed GitHub App slug, a non-numeric installation id, or a github.com vs GHES hostname mismatch — causing createGitHubAppError to be invoked with code 'VALIDATION_ERROR'.","commonSituations":"Passing an empty string for the app slug from unset settings/env; pasting a GHES URL into a github.com-pointed install form or vice versa; whitespace or URL-encoded values in the installation id; tests constructing the error with the wrong discriminant.","solutions":["Inspect the error's `details` field — it carries which input failed validation.","Validate inputs before calling: ensure the app slug is non-empty and installation id is numeric.","Confirm isGhesSelfManaged matches the host you pass (github.com vs a GHES base URL).","Trim and decode any values taken from URL query params before use.","If the classification looks wrong, check that the throw site passes the correct code to createGitHubAppError."],"exampleFix":"// before\nawait completeInstallation(slug) // slug may be ''\n// after\nif (!slug || typeof slug !== 'string' || !slug.trim()) {\n  throw createGitHubAppError('VALIDATION_ERROR', 'App slug is required', { slug })\n}\nawait completeInstallation(slug.trim())","handlingStrategy":"validation","validationCode":"export function assertValidInstallInput(slug: string, installationId: string, isGhesSelfManaged: boolean): void {\n  if (!slug?.trim()) throw createGitHubAppError('VALIDATION_ERROR', 'slug required', { slug })\n  if (!/^\\d+$/.test(String(installationId))) throw createGitHubAppError('VALIDATION_ERROR', 'installationId must be numeric', { installationId })\n  if (isGhesSelfManaged === undefined) throw createGitHubAppError('VALIDATION_ERROR', 'isGhesSelfManaged required')\n}","typeGuard":"function isGitHubAppError(e: unknown): e is GitHubAppError {\n  return e instanceof Error && ['VALIDATION_ERROR','NETWORK_ERROR','AUTH_ERROR','UNKNOWN_ERROR'].includes((e as GitHubAppError).code)\n}","tryCatchPattern":"try {\n  const url = buildInstallUrl(input)\n} catch (e) {\n  if (isGitHubAppError(e) && e.code === 'VALIDATION_ERROR') {\n    console.error('Invalid GitHub App input', e.details)\n  } else { throw e }\n}","preventionTips":["Validate slug/installationId/hostname at form level before calling the helpers.","Trim and decode URL parameters before use.","Keep isGhesSelfManaged derived from the actual host, never hardcoded.","Include the offending value in error `details` for debuggability.","Unit-test each VALIDATION_ERROR branch."],"tags":["github-app","validation","typescript","error-handling"],"backgroundTag":"github-app-validation-error","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"}