-
Notifications
You must be signed in to change notification settings - Fork 0
Troubleshooting
Concrete errors, the cause, and the fix. If the problem you're seeing isn't here, the Discussions tab is the right place to ask.
You forgot the blank import that registers the driver. Every binary that opens a connection needs to import its driver package for its side-effects:
import (
_ "github.com/devituz/lagodev/drivers/postgres" // ← this
// or "/mysql" / "/sqlite"
)go test shows the same error: each test binary needs the driver
package imported somewhere it compiles into.
This is the stdlib driver registration, not lagodev's. The
underlying driver package (mattn/go-sqlite3, lib/pq,
go-sql-driver/mysql) hasn't been imported. Adding _ "github.com/devituz/lagodev/drivers/sqlite" (or /postgres,
/mysql) fixes both — the lagodev wrappers blank-import the
underlying driver in turn.
Another process is holding the migration lock. Causes:
- A previous run crashed mid-migration on a dialect without per-connection lock cleanup (rare; Postgres releases on connection close, but a hung connection can hold a lock until TCP timeout).
- Two CI jobs are deploying the same database at the same time.
Fix:
-- Postgres
SELECT pg_advisory_unlock_all(); -- in a fresh session
SELECT pid, * FROM pg_stat_activity WHERE state = 'idle in transaction';
-- terminate the holder, then re-run migrate
-- MySQL / SQLite
DELETE FROM migrations_lock; -- last-resort manual cleanupBound the wait with lago migrate --lock-timeout=30s so a stuck
deploy fails fast in CI instead of hanging the pipeline.
You edited a migration that's already been applied. The runner hashes the emitted SQL of each applied migration and refuses to proceed if a re-emission produces a different hash, which prevents "works on my machine because I changed Up() after deploying it" divergence.
The right fix is almost always a new migration that does the extra work — never re-edit history.
If you genuinely need to bypass (typically: a non-functional
formatting tweak to the SQL), pass
--no-enforce-checksums to the migrate command, but understand
you're acknowledging the production schema may now differ from
what Up() would produce.
Postgres SSL handshake failed. Fix in .env:
DB_SSL_MODE=disable # local dev
# or
DB_SSL_MODE=require # production with TLSAvailable modes: disable, allow, prefer, require,
verify-ca, verify-full. The default is empty (driver default).
Usually one of:
- An identifier conflicting with a reserved word (
order,group). The schema DSL quotes everything automatically — if you wrote raw SQL viaWhereRaworconn.QueryContext, add backticks yourself. - An unsupported feature for your MySQL version. The schema DSL
targets 5.7+; on 5.6 some
Default()expressions get rejected.
The DB process isn't reachable from where the program is running.
- Docker: forgot
-p 5432:5432, or the container is on a custom network the host isn't on. - Compose: app and DB are in the same
docker-compose.ymlbutDB_HOST=127.0.0.1instead of the service name (DB_HOST=db). - macOS:
127.0.0.1from a container points at the container, not the host. Usehost.docker.internal.
Another process is on the port. Find and stop it:
lsof -i :8080 -sTCP:LISTEN
# kill the PID, or switch ports:
APP_ADDR=:8081 go run .A common culprit is a previous go run . that wasn't cleanly shut
down — pkill -f "go run ./examples/secure" or similar.
The struct didn't declare the incoming field. c.Bind calls
DisallowUnknownFields() so typos in client payloads surface
loudly. Either:
- Add the field to your struct (the right answer if it's legit),
- Tag it with
json:"-"to silence the decoder (rare), - Reject the request as 400 (current behaviour — you saw this message because Bind already wrote the 400).
This is documented in Web-Framework.
The body exceeded the active body limit. Defaults:
-
c.Bindapplies a 1 MiB cap viahttp.MaxBytesReaderwhen noweb.BodyLimit(n)middleware is active. - With
web.BodyLimit(n)applied, that lower limit wins.
Raise the limit:
app.Use(web.BodyLimit(10 << 20)) // 10 MiBFor genuinely huge uploads, stream the body to disk / S3 directly rather than decoding into a struct.
web.CSRF() requires a matching token in both the cookie and the
X-CSRF-Token header (or the _csrf form field). Either:
- Set
web.CSRF()only on routes that need it (don't apply globally to your API if it's auth'd by JWT — JWT-only APIs are CSRF-immune). - Make a
GETrequest first so the middleware issues the cookie, then echo it back in the header for subsequent unsafe methods.
See the Web-Framework secure-by-default section.
Yes — the framework's default Logger() middleware prints status
messages in Uzbek (server tinglamoqda, ro'yxatdan o'tgan marshrutlar). Replace the logger to localise:
app := web.New(/* ... */)
// override the auto-installed middleware with your own logger:
// (advanced) construct a custom Router and pass it in.A simpler workaround is to grep the strings out of structured logs; status codes and request paths are still the canonical events.
go install puts the binary in $(go env GOPATH)/bin. That path
isn't on your PATH by default:
export PATH="$(go env GOPATH)/bin:$PATH"
# add to ~/.zshrc or ~/.bashrcThe CLI falls back to defaults and prints the parse error on
stderr. Fix the JSON and re-run any make:* — the path
configuration takes effect immediately.
The factory definition refers to a struct field that doesn't exist
on the model, or the model has a column:"…" tag that doesn't
match. Cross-check the column name resolved by the reflection cache:
import "github.com/devituz/lagodev/internal/reflectutil"
sch, _ := reflectutil.For(reflect.TypeOf(models.User{}))
fmt.Printf("%+v\n", sch.Columns) // map[string]*Field — keys are column names(Internal package — exported via the test helpers; don't depend on it from production code.)
Normal — those are SQLite's WAL companion files. .gitignore
already excludes them (*.db, *.sqlite, *.sqlite3). They're
deleted automatically when the database is closed cleanly.
Almost always a connection-pool problem in tests that opened a
real database. Switch the test to lagotest.SQLite(t) (in-memory,
fresh per test) — see the Getting-Started testing section.
- FAQ — design questions, not error messages.
-
Configuration —
DB_*reference. - Architecture — when the error makes more sense after seeing the layers.
lagodev on GitHub · MIT-licensed — see LICENSE.