{"record":{"id":"97d765bb34c44a94","repo":"HeyPuter/puter","slug":"not-found-97d765","errorCode":"not_found","errorMessage":"Site not found or not owned by you","messagePattern":"Site not found or not owned by you","errorType":"http","errorClass":"HttpError","httpStatus":404,"severity":"error","filePath":"src/backend/controllers/hosting/HostingController.js","lineNumber":78,"sourceCode":"                    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',\n                        { legacyCode: 'forbidden' },\n                    );\n                }\n\n                await this.subdomainStore.deleteByUuid(site_uuid, {\n                    userId: req.actor.user.id,\n                });\n\n                res.json({});","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/HeyPuter/puter/blob/908ec23eda38526170322c3edf71ba45ecb1ca95/src/backend/controllers/hosting/HostingController.js#L60-L96","documentation":"`POST /delete-site` looked up the subdomain by UUID scoped to the calling user and found no matching row. The store call `subdomainStore.getByUuid(site_uuid, { userId })` returned null, meaning the site does not exist or belongs to a different user. This is an authorization-scoped 404 — the message intentionally does not distinguish the two cases to avoid enumeration.","triggerScenarios":"Passing a `site_uuid` that was deleted already; passing a UUID belonging to another user; passing a stale UUID from an old session; a race where the site was deleted between the list render and the delete click.","commonSituations":"UI shows a stale site list after another tab deleted the same site; user copy-pastes a UUID from someone else's deployment; the site was removed by an admin process.","solutions":["Refresh the site list and retry with the current UUID.","Confirm the authenticated user owns the site — check the list-sites response for the UUID.","If the UUID is correct and owned, check server logs for store errors or DB connectivity issues.","Treat 404 as success in idempotent delete flows (the site is already gone)."],"exampleFix":"// before — assume the site always exists\nawait api.call('delete-site', { site_uuid });\n\n// after — handle 404 idempotently\ntry {\n  await api.call('delete-site', { site_uuid });\n} catch (e) {\n  if (e.code !== 'not_found') throw e;\n  // site already gone — refresh UI\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await api.call('delete-site', { site_uuid });\n} catch (e) {\n  if (e.code === 'not_found') {\n    // Site already deleted or not owned — treat as success in idempotent flows\n    console.log('Site no longer exists; nothing to delete.');\n  } else {\n    throw e;\n  }\n}","preventionTips":["Treat 404 on delete as success — the end state (site gone) is achieved.","Refresh the site list before offering a delete action to avoid stale UUIDs.","Pass only UUIDs from the authenticated user's own site list."],"tags":["hosting","authorization","not-found","http-404","idempotency"],"backgroundTag":null,"analyzedSha":"908ec23eda38526170322c3edf71ba45ecb1ca95","analyzedAt":"2026-08-12T20:53:15.911Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}