{"record":{"id":"7a9d50c0cd588be8","repo":"odysseus-dev/odysseus","slug":"no-email-account-is-configured-for-the-authenticat","errorCode":null,"errorMessage":"No email account is configured for the authenticated owner","messagePattern":"No email account is configured for the authenticated owner","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"mcp_servers/email_server.py","lineNumber":318,"sourceCode":"        \"smtp_ssl\": os.environ.get(\"SMTP_SSL\", \"true\").lower() == \"true\",\n        \"from_address\": os.environ.get(\"EMAIL_FROM\", \"\"),\n        \"archive_folder\": os.environ.get(\"ARCHIVE_FOLDER\", \"Archive\"),\n        \"trash_folder\": os.environ.get(\"TRASH_FOLDER\", \"Trash\"),\n        \"cache_db\": os.environ.get(\n            \"EMAIL_CACHE_DB\",\n            EMAIL_CACHE_DB,\n        ),\n        \"account_id\": None,\n        \"account_name\": None,\n    }\n\n    raw_rows = _read_accounts_from_db()\n    if _mcp_owner_required(raw_rows):\n        raise ValueError(_OWNER_SCOPE_ERROR)\n    rows = _filter_accounts_for_owner(raw_rows)\n    row = _resolve_account_from_rows(rows, account)\n    if _current_owner() and raw_rows and not rows:\n        raise ValueError(\"No email account is configured for the authenticated owner\")\n    if account and rows and not row:\n        available = \", \".join(\n            f\"{r.get('name') or r.get('imap_user')} <{r.get('imap_user') or r.get('from_address') or '?'}>\"\n            for r in rows\n        )\n        raise ValueError(f\"Email account not found for selector {account!r}. Available accounts: {available}\")\n    if row:\n        cfg[\"account_id\"] = row[\"id\"]\n        cfg[\"account_name\"] = row[\"name\"]\n        cfg[\"imap_host\"] = row[\"imap_host\"] or cfg[\"imap_host\"]\n        cfg[\"imap_port\"] = int(row[\"imap_port\"] or cfg[\"imap_port\"])\n        cfg[\"imap_user\"] = row[\"imap_user\"] or cfg[\"imap_user\"]\n        # Passwords in email_accounts are stored encrypted via\n        # src.secret_storage.encrypt — decrypt before handing to IMAP\n        # (same path email_helpers.py:369 uses). Falling back to the raw\n        # ciphertext is what produced AUTHENTICATIONFAILED previously.\n        try:\n            from src.secret_storage import decrypt as _decrypt","sourceCodeStart":300,"sourceCodeEnd":336,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/mcp_servers/email_server.py#L300-L336","documentation":"Raised by the email MCP server's _load_config when an MCP owner is authenticated and the accounts database contains rows, but _filter_accounts_for_owner() leaves zero rows for that owner. It is a ValueError thrown before any IMAP connection is attempted, meaning the multi-owner scoping logic deliberately refuses to fall back to another user's mailboxes.","triggerScenarios":"Calling any email MCP tool (list_emails, send, etc.) while MCP owner auth is active, accounts exist in the email accounts DB, but none of them have owner set to the current authenticated owner.","commonSituations":"Fresh deployment where accounts were seeded under a different/default owner string; owner identifier mismatch (email vs username casing); migrating a single-user setup to multi-owner without re-tagging existing email_accounts rows.","solutions":["Verify which owner the MCP session authenticates as and add/configure an email account row whose owner column matches it exactly","Inspect EMAIL_CACHE_DB rows (owner column) and fix stale owner values or re-create the account via the account-management UI/API under the correct user","If single-user, clear the MCP owner context so owner scoping is not applied"],"exampleFix":"-- accounts table before\nSELECT id, name, owner FROM email_accounts;\n-- rows have owner='admin' but MCP authenticates as 'beagle'\nUPDATE email_accounts SET owner='beagle' WHERE owner='admin';","handlingStrategy":"try-catch","validationCode":"rows = _read_accounts_from_db()\nmine = _filter_accounts_for_owner(rows)\nif _current_owner() and rows and not mine:\n    raise SystemExit('Configure an email account for the current owner first')","typeGuard":"def owner_has_account(rows: list[dict], owner: str | None) -> bool:\n    return not owner or any(r.get('owner') in (None, owner) for r in rows)","tryCatchPattern":"try:\n    cfg = _load_config(account)\nexcept ValueError as e:\n    if 'No email account is configured' in str(e):\n        # onboard an account for this owner, then retry once\n        raise\n    raise","preventionTips":["Seed each real owner's email account at onboarding time","Log the authenticated owner alongside account rows in diagnostics","Never share one account row across owners in multi-owner mode"],"tags":["email","mcp","auth","configuration"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}