{"record":{"id":"f2294cdd788b0386","repo":"HeyPuter/puter","slug":"app-index-url-already-in-use","errorCode":"app_index_url_already_in_use","errorMessage":"App index_url already in use","messagePattern":"App index_url already in use","errorType":"http","errorClass":"HttpError","httpStatus":400,"severity":"warning","filePath":"src/backend/drivers/apps/AppDriver.js","lineNumber":1180,"sourceCode":"            }\n        }\n\n        if (candidates.size === 0) return null;\n        const candidateList = [...candidates];\n        if (hasIndexUrlUniquenessExemption(candidateList)) return null;\n\n        return this.appStore.findByIndexUrlCandidates(candidateList, {\n            excludeAppId,\n        });\n    }\n\n    async #ensureIndexUrlNotAlreadyInUse({ indexUrl, excludeAppId } = {}) {\n        const conflictRow = await this.#findIndexUrlConflictRow({\n            indexUrl,\n            excludeAppId,\n        });\n        if (conflictRow) {\n            throw new HttpError(400, 'App index_url already in use', {\n                legacyCode: 'app_index_url_already_in_use',\n                fields: {\n                    index_url: indexUrl,\n                    app_uid: conflictRow.uid,\n                },\n            });\n        }\n    }\n\n    async #ensurePuterSiteSubdomainIsOwned(indexUrl, user) {\n        if (!user) return;\n        const subdomain = this.#extractPuterHostedSubdomain(indexUrl);\n        if (!subdomain) return;\n\n        let row = await this.stores.subdomain.getBySubdomain(subdomain);\n        if (!row) {\n            // Deploys create the subdomain and immediately point the app\n            // at it, so a replica or peer-cache miss here would wrongly","sourceCodeStart":1162,"sourceCodeEnd":1198,"githubUrl":"https://github.com/HeyPuter/puter/blob/908ec23eda38526170322c3edf71ba45ecb1ca95/src/backend/drivers/apps/AppDriver.js#L1162-L1198","documentation":"Thrown by `#ensureIndexUrlNotAlreadyInUse` when an app row already references the given `index_url` (or its candidate variants) and isn't excluded by `excludeAppId`. Returns HTTP 400 with legacyCode `app_index_url_already_in_use`, carrying `fields.index_url` and `fields.app_uid` of the conflicting app.","triggerScenarios":"Creating/updating an app with an `index_url` that another app already uses, during the non-merge path (`update` with an `excludeAppId` for the current app). `#findIndexUrlConflictRow` resolves origin variants, so scheme/port variants of the same origin also collide.","commonSituations":"Two apps pointed at the same deployed origin; redeploying to an index_url an abandoned app still holds; CDN/origin reuse across app entries.","solutions":["Point the app at a unique origin/index_url.","Update or delete the existing app that holds the conflicting index_url first.","If reassigning within the same app, the update path passes `excludeAppId` so self-conflicts are allowed."],"exampleFix":"// before\ndriver.create({ object: { name:'a', index_url:'https://x.com/i.html' } });\n// another create with same index_url -> 400\n\n// after\nawait driver.update({ uid: existingApp, object: { index_url:'https://x.com/i.html' } });\n// or delete the holder first","handlingStrategy":"validation","validationCode":"// Resolve candidates like the driver does and check before create\nconst conflicts = await appStore.findByIndexUrlCandidates([indexUrl], {});\nif (conflicts.length) throw new Error('index_url already in use');\nawait driver.create({ object: { index_url } });","typeGuard":null,"tryCatchPattern":"try {\n  await driver.create({ object });\n} catch (e) {\n  if (e.code === 'app_index_url_already_in_use') { object.index_url = uniqueOrigin(); await driver.create({object}); return; }\n  throw e;\n}","preventionTips":["Give each app a unique index_url origin.","Reuse/update existing apps rather than re-creating against the same origin.","Remember scheme/port variants of an origin also collide."],"tags":["apps","index-url","conflict","driver"],"backgroundTag":null,"analyzedSha":"908ec23eda38526170322c3edf71ba45ecb1ca95","analyzedAt":"2026-08-12T20:53:15.911Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}