{"record":{"id":"fbe453a008a9e540","repo":"odysseus-dev/odysseus","slug":"selected-model-endpoint-is-not-configured","errorCode":null,"errorMessage":"Selected model endpoint is not configured","messagePattern":"Selected model endpoint is not configured","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"error","filePath":"routes/chat_routes.py","lineNumber":712,"sourceCode":"        try:\n            sess = session_manager.get_session(session)\n        except KeyError:\n            raise HTTPException(404, f\"Session '{session}' not found\")\n        owner = effective_user(request)\n        if _clear_orphaned_session_endpoint(sess, owner=owner):\n            raise HTTPException(400, \"Selected model endpoint was removed. Pick another model in Settings.\")\n\n        # Empty model + live endpoint = setup race (Issue #587). Repair from\n        # the endpoint's cached model list before privilege checks, which\n        # otherwise see \"\" and behave inconsistently with the allowlist.\n        _recover_empty_session_model(sess, session, owner=owner)\n        if not getattr(sess, \"model\", \"\").strip():\n            raise HTTPException(\n                400,\n                \"No model selected for this chat. Open the model picker and choose one before sending.\",\n            )\n        if not (getattr(sess, \"endpoint_url\", \"\") or \"\").strip():\n            raise HTTPException(400, \"Selected model endpoint is not configured\")\n\n        # Same allowed_models + daily-cap gate as chat_stream (mirror so the\n        # non-streaming path can't be used to bypass).\n        _enforce_chat_privileges(request, sess)\n\n        tool_policy = build_effective_tool_policy(last_user_message=message)\n        allow_tool_preprocessing = not tool_policy.block_all_tool_calls\n\n        # Inline memory command\n        memory_response = None\n        if not tool_policy.blocks(\"manage_memory\"):\n            memory_response = await chat_handler.handle_memory_command(sess, message)\n        if memory_response:\n            return {\"response\": memory_response}\n\n        foreground_policy = resolve_foreground_model_policy(\n            owner=owner,\n            allowed_models=_allowed_models_for_request(request),","sourceCodeStart":694,"sourceCodeEnd":730,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/routes/chat_routes.py#L694-L730","documentation":"The session has a model selected but no endpoint_url configured, so the system has nowhere to send the request. This is checked after model validation on the non-streaming path; both must be present for a send to proceed.","triggerScenarios":"Session row has model set but endpoint_url empty — typically a partially initialized session, a manual DB edit, or an endpoint record missing its URL field.","commonSituations":"Endpoint saved without a base URL; session created by a script that set model but not endpoint_url; endpoint record corrupted during migration.","solutions":["Re-select the model/endpoint in the chat so the session gets a full endpoint_url","Fix the endpoint record in Settings to include its base URL","If creating sessions programmatically, always set both model and endpoint_url"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if (!session.endpoint_url || !session.endpoint_url.trim()) { promptEndpointRebind(); return; }","typeGuard":"function hasEndpointUrl(s: {endpoint_url?: string | null}): boolean {\n  return typeof s.endpoint_url === 'string' && s.endpoint_url.trim().length > 0;\n}","tryCatchPattern":null,"preventionTips":["Require both model and endpoint_url when creating sessions via API","Reject endpoint records saved without a base URL"],"tags":["endpoint","configuration","chat","client-error"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}