{"record":{"id":"9467b48ba1546f3f","repo":"t8y2/dbx","slug":"sql-is-required-9467b4","errorCode":null,"errorMessage":"sql is required","messagePattern":"sql is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agents/drivers/xugu/main.go","lineNumber":3853,"sourceCode":"\nfunc selectXuguCatalogTableName(schema, table string, candidates []xuguCatalogTableName) (string, string, error) {\n\tfor _, candidate := range candidates {\n\t\tif candidate.Schema == schema && candidate.Table == table {\n\t\t\treturn candidate.Schema, candidate.Table, nil\n\t\t}\n\t}\n\tif len(candidates) == 1 {\n\t\treturn candidates[0].Schema, candidates[0].Table, nil\n\t}\n\tif len(candidates) == 0 {\n\t\treturn \"\", \"\", fmt.Errorf(\"table not found: %s.%s\", schema, table)\n\t}\n\treturn \"\", \"\", fmt.Errorf(\"table name is ambiguous: %s.%s; specify the catalog's exact case\", schema, table)\n}\n\nfunc (s *server) getExplainInfo(sqlText string) (string, error) {\n\tif strings.TrimSpace(sqlText) == \"\" {\n\t\treturn \"\", errors.New(\"sql is required\")\n\t}\n\trows, err := s.queryRowsWithTimeoutOnce(\"EXPLAIN \"+trimStatementSQL(sqlText), nil, 0)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tdefer s.closeRows(rows)\n\tcolumns, err := rows.Columns()\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tvar builder strings.Builder\n\tfor rows.Next() {\n\t\tvalues, err := scanRow(rows, len(columns))\n\t\tif err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\tbuilder.WriteString(joinValues(values, \"\\t\"))\n\t\tbuilder.WriteByte('\\n')","sourceCodeStart":3835,"sourceCodeEnd":3871,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/xugu/main.go#L3835-L3871","documentation":"Returned by the xugu driver's explain/getExplain path when the SQL statement to explain is empty after trimming. Explain generation requires the statement text; a missing or whitespace-only 'sql' parameter fails validation before any EXPLAIN is issued.","triggerScenarios":"Calling the explain-info path with an empty SQL string, e.g. a completion or plan-preview request whose statement field was never populated.","commonSituations":"Editor integrations sending an explain request before any statement text was typed, or refactored code that lost the statement variable.","solutions":["Pass the actual SQL statement text to getExplainInfo","Trim and validate the SQL string before requesting an explain plan","Guard UI/editor explain actions to be enabled only when statement text exists"],"exampleFix":"// before\nplan, err := getExplainInfo(\"\")\n// after\nif strings.TrimSpace(sqlText) == \"\" { return errors.New(\"sql is required\") }\nplan, err := getExplainInfo(sqlText)","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(sqlText) == \"\" {\n    return fmt.Errorf(\"sql is required\")\n}","typeGuard":"func hasExplainableSQL(sql string) bool {\n    return strings.TrimSpace(sql) != \"\"\n}","tryCatchPattern":"plan, err := s.getExplainInfo(sqlText)\nif err != nil {\n    if err.Error() == \"sql is required\" {\n        return \"\", fmt.Errorf(\"no statement to explain: %w\", err)\n    }\n    return \"\", err\n}","preventionTips":["Only enable EXPLAIN actions when editor statement text is non-empty","Trim the SQL before passing it to explain helpers"],"tags":["validation","xugu","explain","sql"],"backgroundTag":"missing-required-argument","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}