{"record":{"id":"f9cf1e9dcbd62f7f","repo":"gastownhall/beads","slug":"db-rawsql-query-w","errorCode":null,"errorMessage":"db: RawSQL Query: %w","messagePattern":"db: RawSQL Query: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/db/raw_sql.go","lineNumber":23,"sourceCode":"\t\"fmt\"\n\n\t\"github.com/steveyegge/beads/internal/storage/domain\"\n)\n\nfunc NewRawSQLRepository(runner Runner) domain.RawSQLRepository {\n\treturn &rawSQLRepositoryImpl{runner: runner}\n}\n\ntype rawSQLRepositoryImpl struct {\n\trunner Runner\n}\n\nvar _ domain.RawSQLRepository = (*rawSQLRepositoryImpl)(nil)\n\nfunc (r *rawSQLRepositoryImpl) Query(ctx context.Context, query string, args ...any) (*domain.RawSQLResult, error) {\n\trows, err := r.runner.QueryContext(ctx, query, args...)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"db: RawSQL Query: %w\", err)\n\t}\n\tdefer rows.Close()\n\n\tcolumns, err := rows.Columns()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"db: RawSQL Query: columns: %w\", err)\n\t}\n\n\tresult := &domain.RawSQLResult{Columns: columns}\n\tfor rows.Next() {\n\t\tvalues := make([]any, len(columns))\n\t\tptrs := make([]any, len(columns))\n\t\tfor i := range values {\n\t\t\tptrs[i] = &values[i]\n\t\t}\n\t\tif err := rows.Scan(ptrs...); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"db: RawSQL Query: scan: %w\", err)\n\t\t}","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/raw_sql.go#L5-L41","documentation":"RawSQLRepository.Query failed to execute the caller-supplied SQL query. The repository wraps the raw database/sql error, so the wrapped cause is whatever the driver returned for the given query string and args.","triggerScenarios":"Calling Query with invalid SQL syntax, a non-existent table/column, wrong number or type of args for placeholders, or when the database is unreachable/locked.","commonSituations":"Hand-written SQL with typos; queries written for another dialect (MySQL vs Dolt/SQLite); positional placeholder count mismatched with args; read-only connections executing writes; missing migrations.","solutions":["Unwrap the error and read the driver message — it names the exact SQL problem (syntax, no such table, bind count)","Validate the SQL against the actual schema and dialect of the configured database","Match the number of ? placeholders to the number of args, with correct types","Test the same query directly against the database CLI to isolate app vs data issues"],"exampleFix":"// before\nrows, err := rawRepo.Query(ctx, \"SELECT * FROM isues WHERE id = ?\", id)\n// after\nrows, err := rawRepo.Query(ctx, \"SELECT * FROM issues WHERE id = ?\", id)","handlingStrategy":"validation","validationCode":"// validate SQL and table names before executing\nfunc validateSQL(q string) error {\n    if strings.Contains(q, \";\") { return errors.New(\"multiple statements not allowed\") }\n    if !allowedTablesRe.MatchString(q) { return errors.New(\"unknown table reference\") }\n    return nil\n}\n// check placeholder/arg count: strings.Count(q, \"?\") == len(args)","typeGuard":null,"tryCatchPattern":"res, err := rawRepo.Query(ctx, q, args...)\nif err != nil {\n    log.Printf(\"raw query failed: %v (sql=%q)\", errors.Unwrap(err), q)\n    return err\n}","preventionTips":["Test raw SQL against the configured database dialect, not another","Keep placeholder count equal to args length","Run migrations so referenced tables exist","Log the failing SQL alongside the wrapped error"],"tags":["go","database","sql","raw-query"],"backgroundTag":"sql-syntax-or-schema-error","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}