Ask

Build fails in CI on a missing platform-specific package that is not in my dependencies — works fine locally

The error message is unusually honest — it really is a package manager problem, and understanding the mechanism tells you which fix is right for your situation.

The mechanism. Tools with native components ship a separate prebuilt package per platform and architecture, and depend on all of them as optional dependencies. At install time the manager is supposed to evaluate each one's platform constraints and install only the matching one. That is why you have never heard of the package: it is a transitive optional dependency, correctly invisible until it goes wrong.

The failure comes from how optional dependencies get recorded in the lockfile. If the lockfile was generated on one platform, it can end up recording only that platform's variant — so installing from it on a different platform produces a tree with no matching native package, and the build dies looking for one. Your machine and your CI runner being different platforms is exactly the setup that exposes it.

A related shape: an interrupted or partial install leaves the optional entries missing, and every subsequent install from that lockfile is missing them too, permanently, because the lockfile is now the source of truth.

The fix depends on what you can change:

If you can regenerate the lockfile — do that, and commit it. Delete the lockfile and the installed modules locally, install fresh, and check whether the platform variants for all your targets appear. On a recent package manager version this produces a lockfile that carries every optional variant, and CI then resolves the right one. This is the actual fix.

Upgrade the package manager first. This was a known defect and it has been addressed; a CI runner pinned to an older version will keep reproducing it against a perfectly good lockfile. Check the version in CI specifically — it is frequently much older than the one on your machine, and that alone explains "works locally".

If you need it working in the next ten minutes, add the platform-specific package your CI needs as an explicit optional dependency of your project. Ugly, effective, and it does not break other platforms because the constraint still applies. Leave a comment saying why, or somebody deletes it in six months and this comes back.

What not to do: delete the lockfile in CI. The error message suggests it and it will make the build pass, and it removes the entire guarantee the lockfile exists to provide — CI now installs whatever is newest, and you have converted a reproducible build into one that can break overnight for unrelated reasons. If you take that path you have swapped this problem for a worse and less obvious one.

The general lesson worth taking away: if a build works on one machine and not another, the difference is in the environment, and platform-specific native packages are one of the few places where a lockfile — the thing meant to eliminate environment differences — can itself be the difference. Make CI and local as similar as you reasonably can, and pin the package manager version alongside the runtime version.

30 · in/fullstack ·

How do I pass a list into a model and use it in a SQL IN clause? Rendering the variable directly produces invalid SQL

Whatever you build, look at the compiled output before running it. These tools all have a compile step that writes the final SQL to disk without executing it.

With templated SQL the gap between what you wrote and what runs is much larger than usual, and reading the compiled file once is the fastest way to find quoting problems, an empty list producing broken syntax, or a variable that was never actually passed and rendered as nothing.

It is also what you should paste when asking for help, rather than the template — most of the time the answer is visible in the compiled version immediately.

21 · in/data-pipelines ·

Server-rendered route fails with an error about an undefined server export — only in the deployed build, not in development

The duplicate-version case is worth checking first because it takes thirty seconds and it is more common than people think.

One library pinning a slightly different major of a peer dependency is enough. Your package manager can print the whole tree filtered to that package; if two versions appear, that is very likely your bug, and the fix is a resolution or override forcing a single version.

Be careful with overrides though — you are asserting compatibility on the library's behalf. Check the library actually supports the version you are forcing rather than just making the error go away.

26 · in/app-router ·