{"record":{"id":"44eb67ba5e3132be","repo":"HKUDS/DeepTutor","slug":"client-id-and-api-key-are-required","errorCode":null,"errorMessage":"Client ID and API key are required.","messagePattern":"Client ID and API key are required\\.","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"deeptutor/api/routers/knowledge.py","lineNumber":1973,"sourceCode":"def _resolve_ima_credentials(client_id: str, api_key: str) -> ImaCredentials:\n    \"\"\"A request's credentials, falling back to the account-level pair.\n\n    A request that supplies only one half is not silently completed from the\n    account pair: mixing two accounts' halves would fail at IMA with a confusing\n    verdict.\n    \"\"\"\n    supplied = ImaCredentials(client_id=(client_id or \"\").strip(), api_key=(api_key or \"\").strip())\n    if supplied.client_id or supplied.api_key:\n        return supplied\n    return get_account_credentials()\n\n\n@router.post(\"/list-ima\", response_model=ListImaResponse)\nasync def list_ima_route(payload: ListImaRequest):\n    \"\"\"List IMA knowledge bases without storing or echoing credentials.\"\"\"\n    credentials = _resolve_ima_credentials(payload.client_id, payload.api_key)\n    if not credentials.complete:\n        raise HTTPException(status_code=400, detail=\"Client ID and API key are required.\")\n\n    client = ImaClient(\n        ImaConfig(\n            client_id=credentials.client_id,\n            api_key=credentials.api_key,\n            knowledge_base_id=\"\",\n        )\n    )\n    try:\n        return await client.search_knowledge_bases(\n            query=\"\",\n            cursor=payload.cursor.strip(),\n            limit=payload.limit,\n        )\n    except ImaAuthError:\n        raise HTTPException(status_code=401, detail=\"IMA rejected the supplied credentials.\")\n    except ImaRateLimitError:\n        raise HTTPException(status_code=429, detail=\"IMA rate limit reached. Try again shortly.\")","sourceCodeStart":1955,"sourceCodeEnd":1991,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/api/routers/knowledge.py#L1955-L1991","documentation":"HTTP 400 raised when neither the request payload nor the stored credential overrides provide a complete Tencent IMA client_id/api_key pair. The route resolves credentials from payload plus defaults; if the pair is incomplete it refuses to call the IMA API.","triggerScenarios":"POST /list-ima with empty client_id or api_key (or only one of them) and no complete saved defaults; _resolve_ima_credentials().complete is false.","commonSituations":"Forgetting to configure IMA credentials in settings before using the IMA browser, passing only api_key, or env-var names not picked up by the resolver.","solutions":["Provide both client_id and api_key in the request payload","Or configure complete IMA credentials in runtime settings so the resolver finds defaults","Check for whitespace-only credential strings; they strip to empty and count as missing"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const creds = {clientId: clientId?.trim(), apiKey: apiKey?.trim()};\nif (!creds.clientId || !creds.apiKey) throw new Error('IMA client_id and api_key required');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Configure IMA credentials once in runtime settings so every call is pre-authorized"],"tags":["http-400","ima","tencent","credentials","validation"],"backgroundTag":"missing-api-credentials","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}