{"record":{"id":"3c0b77d6918a66db","repo":"bytedance/deer-flow","slug":"failed-to-create-thread","errorCode":null,"errorMessage":"Failed to create thread","messagePattern":"Failed to create thread","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"backend/app/gateway/routers/threads.py","lineNumber":606,"sourceCode":"\n    thread_store = get_thread_store(request)\n    checkpointer = get_checkpointer(request)\n    thread_owner_user_id = get_trusted_internal_owner_user_id(request)\n    thread_owner_kwargs = {\"user_id\": thread_owner_user_id} if thread_owner_user_id else {}\n\n    record = await thread_store.get(thread_id, **thread_owner_kwargs)\n    if record is None and thread_owner_user_id:\n        unscoped_record = await thread_store.get(thread_id, user_id=None)\n        if unscoped_record is not None:\n            if unscoped_record.get(\"user_id\") != thread_owner_user_id:\n                await thread_store.update_owner(thread_id, thread_owner_user_id, user_id=None)\n            record = await thread_store.get(thread_id, **thread_owner_kwargs)\n    if record is None:\n        try:\n            await thread_store.create(thread_id, metadata={}, **thread_owner_kwargs)\n        except Exception:\n            logger.exception(\"Failed to create thread_meta for goal thread %s\", sanitize_log_param(thread_id))\n            raise HTTPException(status_code=500, detail=\"Failed to create thread\") from None\n\n    try:\n        await ensure_thread_checkpoint(checkpointer, thread_id)\n    except Exception:\n        logger.exception(\"Failed to create goal checkpoint for thread %s\", sanitize_log_param(thread_id))\n        raise HTTPException(status_code=500, detail=\"Failed to create thread checkpoint\") from None\n\n\n# ---------------------------------------------------------------------------\n# Endpoints\n# ---------------------------------------------------------------------------\n\n\n@router.delete(\"/{thread_id}\", response_model=ThreadDeleteResponse)\n@require_permission(\"threads\", \"delete\", owner_check=True, require_existing=True)\nasync def delete_thread_data(thread_id: str, request: Request) -> ThreadDeleteResponse:\n    \"\"\"Delete local persisted filesystem data for a thread.\n","sourceCodeStart":588,"sourceCodeEnd":624,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/app/gateway/routers/threads.py#L588-L624","documentation":"Raised by the goal-ensure helper when thread_store.create(thread_id, metadata={}) fails while materializing a thread record for a goal PUT. This is the metadata-store write path (SQL or memory store); any exception during INSERT — connectivity, schema drift, constraint violation — is logged and converted to a 500 'Failed to create thread'.","triggerScenarios":"PUT /api/threads/{thread_id}/goal for a thread_id that has no thread_meta row while the database is unreachable, the thread_meta table is missing (migrations not run), or a duplicate-key/uniqueness error occurs on INSERT.","commonSituations":"Postgres/SQLite down or credentials rotated; alembic/db migrations not applied after upgrade so the thread_meta table or columns don't match; racing two PUT /goal calls for the same brand-new thread id where the loser's INSERT hits the primary key.","solutions":["Read the logged 'Failed to create thread_meta for goal thread %s' traceback to identify the underlying driver error.","Verify database connectivity and that migrations are current (backend make migrate-rev / app startup migration step).","If it is a duplicate-key race, retry the PUT — the second attempt takes the existing-record path and succeeds.","Confirm the thread_id is a plain UUID string; malformed ids that survive validation but break store constraints show up here."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"const healthy = await fetch('/api/health').ok;\nif (!healthy) { /* defer goal PUT until Gateway/db is up */ }","typeGuard":null,"tryCatchPattern":"try { await api.put(`/threads/${id}/goal`, body); }\ncatch (err) {\n  if (err.status === 500 && /Failed to create thread/.test(err.detail)) await delayThenRetryOnce();\n  else throw err;\n}","preventionTips":["Ensure a thread record exists (POST /threads or first run) before PUT /goal.","Keep thread-store migrations applied before upgrading the harness.","Duplicate-key races self-heal on retry — retry the PUT once before alerting."],"tags":["threads","database","goals","http-500","persistence"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}