Skip to content
vibecode_
Go back
Field Log til

TIL: go build ./... does not refresh your daemon binary — embed changes silently no-op

· 2 min read
| Edit on GitHub

What broke

go build ./... recompiled cleanly, exit 0, and the daemon still served the old prompt — because that command writes no binary at all.

We had edited a prompt template baked into our publishing daemon via //go:embed, run go build ./..., and restarted the process. It served the previous prompt. No error, no warning. This is the costliest failure mode: the build reports success while the running behavior never moves.

Why it silently no-ops

Two facts from the Go documentation collide here.

First, //go:embed reads at compile time, not at runtime. The directive initializes the variable “with the contents of files read from the package directory or subdirectories at compile time” (pkg.go.dev/embed). The asset is frozen into the binary; the running process never re-reads disk. Editing the source file changes nothing until something recompiles and replaces the binary.

Second, go build ./... across multiple or non-main packages produces no installable output. It “compiles the packages but discards the resulting object, serving only as a check that the packages can be built” (pkg.go.dev/cmd/go). Nothing is written to $GOBIN; that is go install’s job.

So the two combined exactly: the edited template compiled, the build went green, and the on-disk binary the daemon execs was never rewritten. Embed is what hid the gap — had the daemon read the template from disk at runtime, the mismatch (file new, binary old) would have surfaced on the next request instead of staying invisible.

# what we ran — a compile check, not an artifact
go build ./...        # exit 0, writes nothing deployable

# what deploy actually requires
go build -o /opt/app/daemon ./cmd/daemon   # or: go install ./cmd/daemon
systemctl restart daemon

The lesson

go build ./... answers one question — “does it compile?” — and nothing about deployment.

Keep ./... in CI, where a pass/fail compile check is exactly the contract you want. In the deploy path, do not reuse it: pin an explicit output with -o $ARTIFACT (or go install a single main package), and gate the restart on the artifact being newer than the commit you intend to ship. The boundary between “compiles” and “is deployed” should be enforced by the pipeline, not assumed.

The Beacons Guru References

* Note: These references ground the post in external technical work. Their insights are the light, I am just the mirror.


Edit on GitHub
Share this post on:

Related Posts


Previous
The Agent Crossed the Line: Publishing the Guardrail Logs That Blocked It
Next
Field Ops: The Missing Discipline for Production Agentic Software