{"record":{"id":"a3601989d8cc5c6c","repo":"OtterMind/Chat2DB","slug":"no-database-connection-context-found-call-list-al","errorCode":null,"errorMessage":"No database connection context found. Call list_all_datasources first, then provide dataSourceId/databaseName.","messagePattern":"No database connection context found\\. Call list_all_datasources first, then provide dataSourceId/databaseName\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/ai/AiToolServiceImpl.java","lineNumber":720,"sourceCode":"        String resolvedSchemaName = schemaName;\n\n        if (Objects.isNull(resolvedDataSourceId) && contextProfile != null) {\n            resolvedDataSourceId = contextProfile.getDataSourceId();\n        }\n        if (StringUtils.isBlank(resolvedDatabaseName) && contextProfile != null) {\n            resolvedDatabaseName = contextProfile.getDatabaseName();\n        }\n        if (StringUtils.isBlank(resolvedSchemaName) && contextProfile != null) {\n            resolvedSchemaName = contextProfile.getSchemaName();\n        }\n        if (Objects.nonNull(resolvedDataSourceId)) {\n            final Long scopedDataSourceId = resolvedDataSourceId;\n            final String scopedDatabaseName = resolvedDatabaseName;\n            final String scopedSchemaName = resolvedSchemaName;\n            return invokeWithRequestContext(toolContext,\n                    () -> buildProfile(scopedDataSourceId, scopedDatabaseName, scopedSchemaName));\n        }\n        throw new IllegalArgumentException(\n                \"No database connection context found. Call list_all_datasources first, then provide dataSourceId/databaseName.\");\n    }\n\n    private ConnectionProfile resolveConnectionProfile(AiToolContextRequest toolContext) {\n        if (Objects.isNull(toolContext)) {\n            return null;\n        }\n        if (toolContext.getConnectionProfile() != null) {\n            return toolContext.getConnectionProfile();\n        }\n        Long dataSourceId = toolContext.getDataSourceId();\n        if (Objects.isNull(dataSourceId)) {\n            return null;\n        }\n        String databaseName = toolContext.getDatabaseName();\n        String schemaName = toolContext.getSchemaName();\n        return buildProfile(dataSourceId, databaseName, schemaName);\n    }","sourceCodeStart":702,"sourceCodeEnd":738,"githubUrl":"https://github.com/OtterMind/Chat2DB/blob/5ee1e990e73fbcae1969dc554be254fedb3ab888/chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/ai/AiToolServiceImpl.java#L702-L738","documentation":"Thrown by the AI tool connection resolver when neither an explicit dataSourceId argument, nor a usable ConnectionProfile (from toolContext), yields a non-null resolvedDataSourceId. The message instructs the caller to first list datasources, because the tool layer cannot infer which datasource the SQL/metadata tool should target.","triggerScenarios":"An AI tool invocation (e.g. run_sql, list_schemas) is dispatched with a toolContext whose connectionProfile is null and whose dataSourceId is null, while the per-call dataSourceId argument is also null/blank.","commonSituations":"An LLM tool call omits dataSourceId after the model forgot to call list_all_datasources first; the MCP/tool client did not forward the active datasource session into AiToolContextRequest; a brand-new chat session with no datasource selected.","solutions":["Call the list_all_datasources tool first and capture a valid dataSourceId from its response.","Pass dataSourceId (and databaseName/schemaName when needed) into the next tool request's toolContext.","Ensure the client sets toolContext.dataSourceId or connectionProfile from the active datasource session before invoking any SQL/metadata tool.","If using a pre-established connection, populate toolContext.connectionProfile so resolveConnectionProfile returns non-null."],"exampleFix":"// before\nrun_sql({ sql: \"SELECT 1\" })  // no datasource context\n\n// after\nconst ds = (await list_all_datasources())[0];\nrun_sql({ sql: \"SELECT 1\", dataSourceId: ds.id, databaseName: ds.database });","handlingStrategy":"validation","validationCode":"public void requireDataSourceContext(AiToolContextRequest ctx, Long dataSourceId) {\n    boolean hasArg = dataSourceId != null;\n    boolean hasCtx = ctx != null && (ctx.getDataSourceId() != null\n            || (ctx.getConnectionProfile() != null && ctx.getConnectionProfile().getDataSourceId() != null));\n    if (!hasArg && !hasCtx) {\n        throw new IllegalStateException(\"No datasource context; call list_all_datasources first\");\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    return aiToolService.runSql(toolContext, sql);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"No database connection context found\")) {\n        // prompt the model/user to call list_all_datasources and retry with dataSourceId\n        return needDatasourcePrompt();\n    }\n    throw e;\n}","preventionTips":["Inject the active datasource session id into every AI tool request at the client boundary.","Make list_all_datasources the first tool in any new chat flow.","Add a client-side guard that refuses to dispatch SQL/metadata tools without a dataSourceId."],"tags":["ai-tool","datasource","validation","context"],"backgroundTag":null,"analyzedSha":"5ee1e990e73fbcae1969dc554be254fedb3ab888","analyzedAt":"2026-08-14T07:05:03.077Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}