{"record":{"id":"a3402beadcc3ae03","repo":"Dokploy/dokploy","slug":"github-installation-not-found","errorCode":null,"errorMessage":"Github Installation not found","messagePattern":"Github Installation not found","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"apps/dokploy/pages/api/deploy/github.ts","lineNumber":42,"sourceCode":"} from \"./[refreshToken]\";\n\nconst getGithubRepositoryOwner = (githubBody: any) =>\n\tgithubBody?.repository?.owner?.name ?? githubBody?.repository?.owner?.login;\n\nexport default async function handler(\n\treq: NextApiRequest,\n\tres: NextApiResponse,\n) {\n\tconst signature = req.headers[\"x-hub-signature-256\"];\n\tif (!signature) {\n\t\tres.status(401).json({ message: \"Missing signature header\" });\n\t\treturn;\n\t}\n\n\tconst githubBody = req.body;\n\n\tif (!githubBody?.installation?.id) {\n\t\tres.status(400).json({ message: \"Github Installation not found\" });\n\t\treturn;\n\t}\n\n\tconst githubResult = await db.query.github.findFirst({\n\t\twhere: eq(github.githubInstallationId, githubBody.installation.id),\n\t});\n\n\tif (!githubResult) {\n\t\tres.status(400).json({ message: \"Github Installation not found\" });\n\t\treturn;\n\t}\n\n\tif (!githubResult.githubWebhookSecret) {\n\t\tres.status(400).json({ message: \"Github Webhook Secret not set\" });\n\t\treturn;\n\t}\n\tconst webhooks = new Webhooks({\n\t\tsecret: githubResult.githubWebhookSecret,","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/Dokploy/dokploy/blob/546686ea3587f12ec5652217dedd9f7960fb6d15/apps/dokploy/pages/api/deploy/github.ts#L24-L60","documentation":"The GitHub webhook payload must include installation.id (GitHub App installation events). If githubBody.installation.id is missing the endpoint responds 400 'Github Installation not found'.","triggerScenarios":"Webhook fired for events that carry no installation object (e.g. some repository/organization webhooks configured as plain repo webhooks instead of GitHub App webhooks), or a hand-crafted test payload without installation.","commonSituations":"Configured a standard repository webhook instead of the GitHub App webhook; ping events with unexpected shape; sending a push event from a non-App integration.","solutions":["Use the GitHub App (Dokploy app) webhook flow rather than a plain repo webhook","When testing manually, include \"installation\":{\"id\": <your installation id>} in the payload","Verify the GitHub App is installed on the repository and the event payload is unmodified"],"exampleFix":"// manual test payload must include installation\n{\n  \"installation\": { \"id\": 12345678 },\n  \"action\": \"created\",\n  \"repositories\": [ { \"full_name\": \"org/repo\" } ]\n}","handlingStrategy":"type-guard","validationCode":"if (!req.body?.installation?.id) return res.status(400).json({ message: 'Github Installation not found' });","typeGuard":"const isAppWebhookPayload = (b: any): b is { installation: { id: number } } =>\n  typeof b?.installation?.id === 'number';","tryCatchPattern":"const r = await fetch('/api/deploy/github', ...);\nif (r.status === 400) includeInstallationInNextPayload();","preventionTips":["Use GitHub App webhooks, not plain repo webhooks","Include installation.id in manual test payloads"],"tags":["github","webhook","installation","bad-request"],"backgroundTag":"webhook-payload-invalid","analyzedSha":"546686ea3587f12ec5652217dedd9f7960fb6d15","analyzedAt":"2026-08-27T05:18:58.095Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}