Docs menu
Troubleshooting Go
Common build and runtime errors for Go apps on Primcloud, with the fix for each.
On this page
Two places to look when a deploy misbehaves:
- Build log: the Deployments tab streams the full build output, including every
go installandgo listinvocation. Build errors and Go compiler errors surface here. - Runtime log: the Logs tab streams
stdoutandstderrfrom your running pods. Startup crashes, unhandled panics, and connection errors show up here.
This page lists the errors that come up most often, in the order they'd typically bite you: detection, go.mod config, version resolution, compile, then runtime.
Common build errors#
No Go application found#
The build looked for a go.mod at the repo root and found none.
Fix. Add a go.mod (go mod init example.com/myapp) and commit it. If your Go project is a subdirectory of a larger monorepo, import that subdirectory as its own Primcloud app.
go.mod parse error#
The go directive or the // +heroku goVersion directive in go.mod couldn't be read. Usually the version string is malformed or the directive line is misspelled.
Fix. Confirm the file has a valid go X.Y or go X.Y.Z line, and that any // +heroku goVersion comment is exactly that: //, then +heroku, then goVersion, then a version constraint. Run go mod tidy locally if you're unsure.
Couldn't resolve go version#
The version requested by go.mod (or by // +heroku goVersion) has no match among the available SDKs. Either the version isn't a real release, it predates what's available, or a =1.20.14-style exact pin names a patch that isn't there.
Fix. Bump to a version that resolves (see Runtime versions), or loosen the constraint (drop the leading =, or bump the minor line) so the resolver can pick a close match.
go list failed#
go list ran to enumerate main packages and exited non-zero. The compiler's error message sits directly above this one in the build log. Common causes:
- Missing modules. A dependency in
go.modcouldn't be downloaded: a private repo without credentials, a deleted upstream module, a network issue. CheckGOPRIVATEand any authentication env vars. go.summismatch. A checksum doesn't line up with the downloaded content. Rungo mod tidyandgo mod verifylocally, then commit the updated files.- Compile-time issues in the code being listed.
go listparses source files, so a syntax error anywhere in the module can trip it.
Fix. Reproduce locally with go list -tags heroku ./..., the same command the build runs.
Couldn't run go build#
go install -tags heroku ran and the compiler exited non-zero. Anything a normal Go compile can fail on lands here: type errors, missing imports, cgo failures, resource limits.
Fix. Read the compiler output in the build log. To reproduce locally:
GOOS=linux go install -tags heroku ./...
If the failure is cgo-related and mentions a missing .h header or an undefined reference to a C symbol, install the required -dev package through project.toml; see Customizing the build → Debian packages. If you don't actually need cgo, set CGO_ENABLED=0 in the Secrets panel.
Invalid Go package import path#
Raised when a process name can't be derived from a package because its import path has no /, for example, a bare main at the module root with no proper import path. Process names come from the trailing segment of the import path.
Fix. Give your main packages proper import paths under the module: move them into cmd/<name>/ subdirectories, or name them explicitly with // +heroku install in go.mod.
Invalid process name#
Raised when the trailing segment of a package's import path isn't a valid process name. Names must match [A-Za-z0-9_-]+. A package under example.com/myapp/cmd/[weird] won't work.
Fix. Rename the package directory to use only letters, digits, hyphens, and underscores, or use // +heroku install to name the packages you want compiled with a valid path suffix.
Common runtime errors#
App doesn't bind to $PORT#
Symptom: the deployment reaches Release Succeeded but the URL returns a connection error, and the runtime log shows the process running without a "listening on" line.
Unlike some language runtimes, the Go build does not rewrite your launch command to inject the port. Your code has to read $PORT itself.
Fix. In your web entrypoint:
port := os.Getenv("PORT")
if port == "" {
log.Fatal("$PORT must be set")
}
if err := http.ListenAndServe(":"+port, nil); err != nil {
log.Fatal(err)
}
Primcloud sets PORT to 5000 on the web formation and routes traffic only there. Hard-coding a port, or leaving it at a framework default like 8080, means requests never reach your app.
App exits immediately on start#
The runtime log shows the process starting and then exiting with a non-zero code, with no other output.
Most common causes:
- Panic during init. A
func init()panicked beforemainhad a chance to log. Recover inmainand log the error tostderr:defer func() { if r := recover(); r != nil { log.Printf("panic: %v", r) panic(r) } }() - Missing required env var. If your app reads a connection string or API key and calls
log.Fatalon empty, set it in the Secrets panel and redeploy. - Wrong architecture. If you cross-compile locally with an unusual
GOOS/GOARCHand ship the binary in-repo, it might not match the pod's architecture. Let Primcloud build from source instead.
Missing shared library at runtime#
error while loading shared libraries: libpq.so.5: cannot open shared object file
Your compiled binary dynamically links against a shared library that isn't in the run image. This usually comes from cgo dependencies: github.com/mattn/go-sqlite3 (needs libsqlite3), github.com/lib/pq in cgo mode (needs libpq), and similar.
Fix. Install the missing package through project.toml; see Customizing the build → Debian packages. Or, if the package supports a pure-Go build, set CGO_ENABLED=0 and rebuild.
Multiple processes but no web in the formation#
Symptom: the app has multiple main packages, the build succeeds, the Deployments log shows each process registered, but the formation only starts non-web processes and the URL returns a connection error.
A default web process is always registered. If a compiled package is named web, that one is used; otherwise the first package's command is duplicated under the web process type. If you're seeing this, check which package became web in the Deployments log where launch processes are registered.
Fix. Either rename the package you want as the web entrypoint to web (move it to cmd/web/), or ship a Procfile at the repo root that names the web command explicitly:
web: server
worker: worker
Debugging tips#
- Reproduce the build locally.
GOOS=linux go install -tags heroku ./...runs the same command the build runs. Most build failures reproduce this way. - Check the resolved Go version. The build log reports which SDK it picked. Compare it to what your
go.modasked for. A resolution surprise usually points at a misplaced// +heroku goVersiondirective. - Verify checksums locally before pushing.
go mod tidy && go mod verifycatches mostgo.summismatches before they reach Primcloud.