{"record":{"id":"31e269cd8d698894","repo":"bytebase/bytebase","slug":"database-is-required-31e269","errorCode":null,"errorMessage":"database is required","messagePattern":"database is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/api/mcp/tool_schema.go","lineNumber":235,"sourceCode":"- Write a query: get_schema(database=\"employee\", include=\"columns\") → all tables with columns\n\n**Notes:**\n- Metadata is auto-synced on access. The first call to a stale database may take longer.\n- For databases with many tables, columns/details modes return up to 200 tables PER SCHEMA.\n  Use schema= or table= to narrow further.\n- Column masking metadata is only returned when table= is set.\n- Requires bb.databases.getSchema permission.`\n\nfunc (s *Server) registerSchemaTool() {\n\tmcp.AddTool(s.mcpServer, &mcp.Tool{\n\t\tName:        \"get_schema\",\n\t\tDescription: getSchemaDescription,\n\t}, s.handleGetSchema)\n}\n\nfunc (s *Server) handleGetSchema(ctx context.Context, req *mcp.CallToolRequest, input SchemaInput) (*mcp.CallToolResult, any, error) {\n\tif input.Database == \"\" {\n\t\treturn nil, nil, errors.New(\"database is required\")\n\t}\n\n\tinclude, err := resolveIncludeLevel(input)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tresolved, resolveResult := s.resolveTarget(ctx, req, input.Database, input.Instance, input.Project)\n\tif resolveResult != nil {\n\t\treturn resolveResult, nil, nil\n\t}\n\n\t// On engines that don't expose named schemas (MySQL, TiDB, ClickHouse, etc.),\n\t// drop the schema filter and note the drop. The backend applies `schema == \"...\"`\n\t// as an exact match, so passing a non-empty hint like \"public\" on MySQL would\n\t// filter out every table. Results are still returned; the note tells the caller\n\t// why the parameter was ignored.\n\tvar warnings []string","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/bytebase/bytebase/blob/1870550677fe08f0d2a78c07acd27541464eb945/backend/api/mcp/tool_schema.go#L217-L253","documentation":"The MCP `getSchema` tool resolves schema metadata for a specific database, so `input.Database` must be set. `database is required` is returned immediately when it is empty, before resolving the include level or checking permissions. TestGetSchema_MissingDatabase exercises exactly this path.","triggerScenarios":"Calling the `getSchema` MCP tool with `input.Database == \"\"` — omitting the `database` argument or passing an empty string; also whitespace-only values not rejected before this check.","commonSituations":"An AI agent skips database discovery and guesses the call; a workflow propagates an empty variable after a failed lookup; the caller confuses schema name with database name.","solutions":["Pass a concrete database resource name in the `database` field.","Resolve the target database via the discovery tooling before calling getSchema.","Validate the argument non-empty (after trimming) client-side."],"exampleFix":"// before\nSchemaInput{Include: \"tables\"}\n// after\nSchemaInput{Database: \"instances/prod/databases/appdb\", Include: \"tables\"}","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(input.Database) == \"\" { return errors.New(\"database is required before calling getSchema\") }","typeGuard":"func hasDatabase(in SchemaInput) bool { return strings.TrimSpace(in.Database) != \"\" }","tryCatchPattern":"result, err := getSchemaTool(ctx, input)\nif err != nil && strings.Contains(err.Error(), \"database is required\") {\n    return fmt.Errorf(\"getSchema needs a database resource name: %w\", err)\n}","preventionTips":["Resolve the database via discovery tooling before schema lookup","Distinguish database name from schema name in client configs","Validate required arguments before tool invocation"],"tags":["mcp","validation","missing-required-field"],"backgroundTag":"missing-required-argument","analyzedSha":"1870550677fe08f0d2a78c07acd27541464eb945","analyzedAt":"2026-09-06T21:16:13.665Z","contentChangedAt":"2026-09-06T21:16:13.665Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}