{"record":{"id":"05a457632ad1a79b","repo":"HeyPuter/puter","slug":"bad-request-05a457","errorCode":"bad_request","errorMessage":"Missing or invalid `site_uuid`","messagePattern":"Missing or invalid `site_uuid`","errorType":"http","errorClass":"HttpError","httpStatus":400,"severity":"error","filePath":"src/backend/controllers/hosting/HostingController.js","lineNumber":69,"sourceCode":"                allowFullAccessToken: true,\n                requireVerified: true,\n                // Destructive, and pairs with the `subdomains:create`\n                // budget on the driver side.\n                rateLimit: {\n                    scope: 'delete-site',\n                    limit: 60,\n                    window: 60_000,\n                    key: 'user',\n                    bySubscription: {\n                        [DEFAULT_FREE_SUBSCRIPTION]: 30,\n                        [DEFAULT_TEMP_SUBSCRIPTION]: 10,\n                    },\n                },\n            },\n            async (req, res) => {\n                const { site_uuid } = req.body ?? {};\n                if (!site_uuid || typeof site_uuid !== 'string') {\n                    throw new HttpError(400, 'Missing or invalid `site_uuid`', {\n                        legacyCode: 'bad_request',\n                    });\n                }\n\n                const row = await this.subdomainStore.getByUuid(site_uuid, {\n                    userId: req.actor.user.id,\n                });\n                if (!row) {\n                    throw new HttpError(\n                        404,\n                        'Site not found or not owned by you',\n                        { legacyCode: 'not_found' },\n                    );\n                }\n                if (row.protected) {\n                    throw new HttpError(\n                        403,\n                        'Cannot delete a protected subdomain',","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/HeyPuter/puter/blob/908ec23eda38526170322c3edf71ba45ecb1ca95/src/backend/controllers/hosting/HostingController.js#L51-L87","documentation":"The `POST /delete-site` endpoint requires a `site_uuid` string in the JSON request body. The controller validates the field immediately and rejects with HTTP 400 if it is missing, not a string, or empty. This is a client-side input error — the request never reaches the store layer.","triggerScenarios":"Calling `POST /api/delete-site` with a body that omits `site_uuid`, passes a number/object/null, or passes an empty string. Also fires if the body is not parsed as JSON (wrong Content-Type) so `req.body` is undefined.","commonSituations":"Frontend sends the UUID from the wrong field name (e.g., `uuid` instead of `site_uuid`); the value is undefined because the site list row was null; a test harness posts an incomplete fixture.","solutions":["Ensure the request body is valid JSON with a `site_uuid` field set to the site's UUID string.","Set the `Content-Type: application/json` header so Express parses the body.","Confirm the UUID comes from a prior list-sites or create-site response, not a fabricated value.","Add a client-side check that `site_uuid` is a non-empty string before posting."],"exampleFix":"// before\nawait fetch('/api/delete-site', {\n  method: 'POST',\n  body: JSON.stringify({ uuid: site.id }), // wrong field name\n});\n\n// after\nawait fetch('/api/delete-site', {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body: JSON.stringify({ site_uuid: site.uuid }),\n});","handlingStrategy":"validation","validationCode":"function isValidSiteUuid(v) {\n  return typeof v === 'string' && v.length > 0;\n}\n\n// before calling\nif (!isValidSiteUuid(site.uuid)) {\n  throw new Error('Cannot delete: site UUID is missing');\n}\nawait fetch('/api/delete-site', {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body: JSON.stringify({ site_uuid: site.uuid }),\n});","typeGuard":"/** @param {unknown} v @returns {v is string} */\nfunction isNonEmptyString(v) {\n  return typeof v === 'string' && v.length > 0;\n}","tryCatchPattern":"try {\n  const res = await fetch('/api/delete-site', {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify({ site_uuid }),\n  });\n  if (!res.ok) throw await res.json();\n} catch (e) {\n  if (e.code === 'bad_request') {\n    console.error('site_uuid is missing or invalid:', e.message);\n  }\n}","preventionTips":["Always send `Content-Type: application/json` for POST endpoints that read `req.body`.","Derive `site_uuid` from a trusted list-sites response, not user input.","Validate the UUID is a non-empty string before constructing the request."],"tags":["validation","hosting","api-input","http-400","bad-request"],"backgroundTag":null,"analyzedSha":"908ec23eda38526170322c3edf71ba45ecb1ca95","analyzedAt":"2026-08-12T20:53:15.911Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}