{"record":{"id":"e844a4edd6fc8f63","repo":"HKUDS/DeepTutor","slug":"t-api-partner-not-found-or-not-running","errorCode":null,"errorMessage":"t(\"api.partner_not_found_or_not_running\")","messagePattern":"t\\(\"api\\.partner_not_found_or_not_running\"\\)","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"error","filePath":"deeptutor/api/routers/partners.py","lineNumber":803,"sourceCode":"    mgr.save_config(partner_id, cfg)\n    return _stopped_partner_dict(partner_id, cfg)\n\n\n@router.post(\"/{partner_id}/start\", dependencies=_MANAGEABLE)\nasync def start_partner(partner_id: str):\n    instance = await _ensure_running_partner(partner_id, allow_stopped=True)\n    # An explicit start is a persisted \"run on boot\" intent — so the partner\n    # comes back in this state after a DeepTutor restart (a manual /stop clears\n    # it; a lazy chat-driven start does NOT reach here, so it can't flip it).\n    get_partner_manager().save_config(partner_id, instance.config, auto_start=True)\n    return instance.to_dict(mask_secrets=True)\n\n\n@router.post(\"/{partner_id}/stop\", dependencies=_MANAGEABLE)\nasync def stop_partner(partner_id: str):\n    stopped = await get_partner_manager().stop_partner(partner_id)\n    if not stopped:\n        raise HTTPException(status_code=404, detail=t(\"api.partner_not_found_or_not_running\"))\n    return {\"partner_id\": partner_id, \"stopped\": True}\n\n\n@router.delete(\"/{partner_id}\", dependencies=_MANAGEABLE)\nasync def destroy_partner(partner_id: str):\n    destroyed = await get_partner_manager().destroy_partner(partner_id)\n    if not destroyed:\n        raise HTTPException(status_code=404, detail=t(\"api.partner_not_found\"))\n    return {\"partner_id\": partner_id, \"destroyed\": True}\n\n\n@router.post(\"/{partner_id}/channels/reload\", dependencies=_MANAGEABLE)\nasync def reload_partner_channels(partner_id: str):\n    mgr = get_partner_manager()\n    instance = mgr.get_partner(partner_id)\n    if not instance or not instance.running:\n        raise HTTPException(status_code=404, detail=t(\"api.partner_not_running\"))\n    try:","sourceCodeStart":785,"sourceCodeEnd":821,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/api/routers/partners.py#L785-L821","documentation":"404 raised by the DELETE-stop route POST /api/partners/{partner_id}/stop when PartnerManager.stop_partner() returns a falsy value, meaning no partner with that id exists or it was not in a running state to stop. It is an explicit FastAPI HTTPException, so it always surfaces as an HTTP 404 with the i18n message 'api.partner_not_found_or_not_running'.","triggerScenarios":"Calling POST /partners/{id}/stop with an id that was never created, was already destroyed, or is already stopped (stop_partner returns False when nothing transitioned).","commonSituations":"UI holds a stale partner list after another tab destroyed the partner; double-clicking Stop fires the second request after the first already stopped it; typo'd partner_id from env/config.","solutions":["Verify the partner exists and its running state via GET /partners before stopping (or use the list from GET /partners)","Re-sync the partner list (GET /partners) and confirm the id, then retry the stop","If the id is stale because the partner was destroyed, drop it from your UI state instead of retrying"],"exampleFix":"// before\nawait client.post(f\"/partners/{partner_id}/stop\")\n// after\npartners = (await client.get(\"/partners\")).json()\nif any(p[\"partner_id\"] == partner_id for p in partners):\n    await client.post(f\"/partners/{partner_id}/stop\")","handlingStrategy":"validation","validationCode":"partners = (await client.get(\"/api/v1/partners\")).json()\nids = {p[\"partner_id\"] for p in partners}\nassert partner_id in ids, \"partner does not exist\"","typeGuard":null,"tryCatchPattern":"except HTTPStatusError as e:\n    if e.response.status_code == 404:\n        # already stopped or unknown id — refresh state","preventionTips":["Cache the partner list and refresh before lifecycle calls","Disable the Stop button once a stop request is in flight"],"tags":["http-404","partners","fastapi","lifecycle"],"backgroundTag":"resource-not-found","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}