Version
v1.31.1 (also reported against this parser behavior in an internal ADR while on v1.31.0/v1.31.1; no newer release exists as of 2026-08-12 to retest against)
What happened?
When a sqlite-engine query file has more than one named query and an earlier query is missing its trailing ;, sqlc fails the first query with a self-referential duplicate query name error instead of parsing the two queries as separate statements. With the semicolon added, generation succeeds.
We also independently hit a related but different symptom of what looks like the same underlying query-boundary bug: in a file with many (~17+) named queries, one query's generated SQL string had 1–2 trailing characters of the previous query's identifier bleed into it (e.g. a column reference generated as last_seen_ instead of last_seen_at), producing a runtime no such column: last_seen_ error rather than a compile-time failure. We don't yet have a minimal repro isolated for that variant, but suspect the same query-splitting logic is at fault, since both manifestations disappear once every query is terminated with an explicit ; (or split into one-query-per-file, our current workaround).
Minimal reproduction
sqlc.yaml:
version: "2"
sql:
- engine: "sqlite"
schema: "schema.sql"
queries: "queries"
gen:
go:
package: "db"
out: "db"
schema.sql:
CREATE TABLE widgets (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
detected_at TEXT NOT NULL,
synced_at TEXT
);
CREATE TABLE gadgets (
id TEXT PRIMARY KEY,
ecosystem TEXT NOT NULL,
detected_at TEXT NOT NULL,
synced_at TEXT
);
queries/widgets.sql — note the first query has no trailing ;:
-- name: GetUnsyncedWidgets :many
SELECT id, name, detected_at
FROM widgets
WHERE synced_at IS NULL
-- name: GetUnsyncedGadgets :many
SELECT id, ecosystem, detected_at
FROM gadgets
WHERE synced_at IS NULL
LIMIT 500;
Running sqlc generate:
# package db
queries\widgets.sql:1:1: duplicate query name: GetUnsyncedWidgets
Only one query is named GetUnsyncedWidgets in the file — the error is spurious, and the location (1:1) points at the wrong query entirely.
Expected behaviour
sqlc generate succeeds and generates both GetUnsyncedWidgets and GetUnsyncedGadgets, the same as when a trailing ; is added after the first query's WHERE synced_at IS NULL line (verified — this alone is sufficient to make the same file generate cleanly).
Additional context
We hit this while consolidating per-query .sql files for the sqlite engine (each query currently lives in its own file specifically to route around this class of bug, tracked internally as an ADR). Would like to re-consolidate to one file per table (matching our Postgres-engine convention) once this is fixed. Happy to provide the ~17-query file that produced the truncated-identifier variant if useful, or help narrow further.
sql_package/other gen options are irrelevant to reproduction — same failure with defaults.
Version
v1.31.1 (also reported against this parser behavior in an internal ADR while on v1.31.0/v1.31.1; no newer release exists as of 2026-08-12 to retest against)
What happened?
When a
sqlite-engine query file has more than one named query and an earlier query is missing its trailing;, sqlc fails the first query with a self-referentialduplicate query nameerror instead of parsing the two queries as separate statements. With the semicolon added, generation succeeds.We also independently hit a related but different symptom of what looks like the same underlying query-boundary bug: in a file with many (~17+) named queries, one query's generated SQL string had 1–2 trailing characters of the previous query's identifier bleed into it (e.g. a column reference generated as
last_seen_instead oflast_seen_at), producing a runtimeno such column: last_seen_error rather than a compile-time failure. We don't yet have a minimal repro isolated for that variant, but suspect the same query-splitting logic is at fault, since both manifestations disappear once every query is terminated with an explicit;(or split into one-query-per-file, our current workaround).Minimal reproduction
sqlc.yaml:schema.sql:queries/widgets.sql— note the first query has no trailing;:Running
sqlc generate:Only one query is named
GetUnsyncedWidgetsin the file — the error is spurious, and the location (1:1) points at the wrong query entirely.Expected behaviour
sqlc generatesucceeds and generates bothGetUnsyncedWidgetsandGetUnsyncedGadgets, the same as when a trailing;is added after the first query'sWHERE synced_at IS NULLline (verified — this alone is sufficient to make the same file generate cleanly).Additional context
We hit this while consolidating per-query
.sqlfiles for thesqliteengine (each query currently lives in its own file specifically to route around this class of bug, tracked internally as an ADR). Would like to re-consolidate to one file per table (matching our Postgres-engine convention) once this is fixed. Happy to provide the ~17-query file that produced the truncated-identifier variant if useful, or help narrow further.sql_package/other gen options are irrelevant to reproduction — same failure with defaults.