{"record":{"id":"885854e2e1d18fb9","repo":"bytedance/deer-flow","slug":"failed-to-switch-lark-app-credentials","errorCode":null,"errorMessage":"Failed to switch Lark app credentials.","messagePattern":"Failed to switch Lark app credentials\\.","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"backend/app/gateway/routers/integrations.py","lineNumber":354,"sourceCode":"    try:\n        result = await asyncio.to_thread(\n            set_lark_app_credentials,\n            get_effective_user_id(),\n            config,\n            app_id=body.app_id,\n            app_secret=body.app_secret,\n            brand=body.brand,\n        )\n        return _config_complete_to_response(result, include_host_paths=await _is_admin_user(request))\n    except FileNotFoundError as e:\n        raise HTTPException(status_code=404, detail=str(e))\n    except ValueError as e:\n        raise HTTPException(status_code=400, detail=str(e))\n    except TimeoutError as e:\n        raise HTTPException(status_code=504, detail=str(e))\n    except Exception as e:\n        logger.error(\"Failed to switch Lark app credentials: %s\", e, exc_info=True)\n        raise HTTPException(status_code=500, detail=\"Failed to switch Lark app credentials.\")\n\n\n@router.post(\"/lark/auth/start\", response_model=LarkAuthStartResponse, summary=\"Start Lark/Feishu Browser Authorization\")\nasync def start_lark_browser_auth(body: LarkAuthStartRequest) -> LarkAuthStartResponse:\n    try:\n        result = await asyncio.to_thread(\n            start_lark_auth,\n            get_effective_user_id(),\n            domains=tuple(body.domains),\n            scope=body.scope,\n            recommend=body.recommend,\n            generation=body.generation,\n        )\n        return _auth_start_to_response(result)\n    except FileNotFoundError as e:\n        raise HTTPException(status_code=404, detail=str(e))\n    except LarkFlowSupersededError as e:\n        raise HTTPException(status_code=409, detail=str(e))","sourceCodeStart":336,"sourceCodeEnd":372,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/app/gateway/routers/integrations.py#L336-L372","documentation":"Generic 500 catch-all for POST /lark/config/credentials (integrations.py:354). Unexpected exceptions from set_lark_app_credentials — CLI subprocess OS errors, unexpected JSON, crashes writing credential files — are logged with traceback and surfaced as this opaque 500.","triggerScenarios":"lark-cli binary present but failing to execute (permissions, exec format), credential file write OSError, status probe raising after the switch committed.","commonSituations":"Corrupt managed CLI install, architecture-mismatched binary, read-only credential directory.","solutions":["Read the 'Failed to switch Lark app credentials:' traceback in Gateway logs","Confirm the managed lark-cli binary executes: run it manually as the Gateway user","Check GET /lark/status afterwards — the switch may have partially applied before the failure; retry only if status shows the old app","Reinstall via POST /lark/install to repair a corrupt CLI"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await switchCreds(body); } catch (e) {\n  if (e?.response?.status === 500) { await api.get('/integrations/lark/status').then(report); }\n}","preventionTips":["Verify the managed lark-cli executes as the Gateway user during deployment smoke tests","Reconcile with GET /lark/status after 500s since the switch may partially commit"],"tags":["lark","feishu","http-500","credentials","gateway","cli"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}