{"record":{"id":"1fa760c6890e2c29","repo":"HeyPuter/puter","slug":"bad-request","errorCode":"bad_request","errorMessage":"Failed to batch write all items to DynamoDB","messagePattern":"Failed to batch write all items to DynamoDB","errorType":"http","errorClass":"HttpError","httpStatus":400,"severity":"error","filePath":"src/backend/clients/dynamodb/DDBClient.ts","lineNumber":312,"sourceCode":"                if (Object.keys(unprocessedItems).length === 0) {\n                    requestItems = {};\n                    break;\n                }\n\n                requestItems = unprocessedItems as NonNullable<\n                    BatchWriteCommandInput['RequestItems']\n                >;\n                if (attempt < MAX_BATCH_WRITE_RETRIES) {\n                    const delayMs = Math.min(\n                        1000,\n                        BATCH_WRITE_RETRY_BASE_MS * 2 ** attempt,\n                    );\n                    await sleep(delayMs);\n                }\n            }\n\n            if (Object.keys(requestItems).length > 0) {\n                throw new HttpError(\n                    400,\n                    'Failed to batch write all items to DynamoDB',\n                    { legacyCode: 'bad_request' },\n                );\n            }\n        }\n\n        return {\n            ConsumedCapacity: Array.from(consumedCapacityByTable.entries()).map(\n                ([TableName, CapacityUnits]) => ({\n                    TableName,\n                    CapacityUnits,\n                }),\n            ),\n        };\n    }\n\n    @Span('ddb.del', (table: string) => ({ 'db.table': table }))","sourceCodeStart":294,"sourceCodeEnd":330,"githubUrl":"https://github.com/HeyPuter/puter/blob/908ec23eda38526170322c3edf71ba45ecb1ca95/src/backend/clients/dynamodb/DDBClient.ts#L294-L330","documentation":"App names are globally unique. create() checks existsByName(fields.name) and, when a match is found and options.dedupe_name is NOT set, throws 400 app_name_already_in_use with the user-facing message. This is the default path; dedupe_name is opt-in.","triggerScenarios":"Calling puter.apps.create({ name }) where `name` is already taken by any app in the system (owned by anyone). Most common on retries/re-imports or when picking a generic name.","commonSituations":"Re-running a setup script that already created the app; choosing a common name like 'admin' or 'dashboard'; an old app row was not deleted before re-creating.","solutions":["Choose a unique name (include a namespace prefix or random suffix).","Pass options.dedupe_name:true to let the driver auto-suffix (beware the dedupe backstop above).","Re-use the existing app via update() instead of create() if it is the same app.","select() by name first to detect the collision and branch accordingly."],"exampleFix":"// before\nawait puter.apps.create({ name: 'dashboard' });\n\n// after — branch on existence\nconst existing = await puter.apps.list({ predicate: ['user-can-edit'] });\nconst mine = existing.find(a => a.name === 'dashboard');\nif (mine) await puter.apps.update(mine.uid, { index_url });\nelse await puter.apps.create({ name: 'dashboard', index_url });","handlingStrategy":"validation","validationCode":"// Check the name is free before create().\nconst taken = await puter.apps.list({ predicate: ['user-can-edit'] });\nconst nameExists = taken.some(a => a.name === candidate);\nif (nameExists) { /* pick another or update() the existing */ }","typeGuard":null,"tryCatchPattern":"try { await puter.apps.create({ name }); }\ncatch (e) {\n  if (e?.code === 'app_name_already_in_use') { await puter.apps.create({ name }, { dedupe_name: true }); }\n  else throw e;\n}","preventionTips":["Pick namespaced/unique names at create time.","Re-use update() for re-imports of the same app instead of create().","Pre-screen against list() before bulk creates."],"tags":["apps","naming","uniqueness","validation"],"backgroundTag":null,"analyzedSha":"908ec23eda38526170322c3edf71ba45ecb1ca95","analyzedAt":"2026-08-12T20:53:15.911Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}