Skip to content

Troubleshooting a failed build

Mattias Carlsson edited this page Sep 3, 2026 · 1 revision

Troubleshooting a failed build

A build stopped, or finished and produced something wrong. This page is the order to check things in.

For static-build setup per distribution — which system libraries need .a versions and how to get them — see BUILDING.md, which stays in the repository because those package names are version-bound.

First: read the log, because it is still there

When a recipe fails, mediaforge does three things — prints the whole log to your terminal, leaves the file on disk, and stops with

[mediaforge] FATAL: Command failed (exit 1): make -j16

The file is at workspace/.logs/<package>-<phase>.log, where phase is configure, build or install:

ls workspace/.logs/
# libass-configure.log
# x265-build.log

A log that exists is a failure. Successful recipes delete their own log, so the directory is empty on a clean run. If you scrolled past the output, the file is the same content — you have not lost it.

For a configure-time link failure, the more specific answer is usually in the package's own log rather than mediaforge's:

less packages/<package>/config.log            # autotools
less packages/FFmpeg-release-*/ffbuild/config.log   # FFmpeg itself

Retry just the one recipe

Builds are gated by stamp files in workspace/.stamps/, one per package, named <name>-<version>. Delete the stamp and the next build redoes that package and nothing else:

ls workspace/.stamps/
rm workspace/.stamps/x264-*
./mediaforge.sh build --enable-gpl

Pass the same flags as the original build. This is the trap: the mutex-group choices are stored in $PREFIX/.mediaforge-choices and come back automatically, but the licence tier is not stored. save_stored_choices writes only the six group choices and the trust-store path — --enable-gpl and --enable-nonfree are not among them. So a bare ./mediaforge.sh build after an --enable-nonfree build resolves to a different set of recipes, and the rebuild will not match the tree it is joining.

"already built" / "outdated but will not be rebuilt"

Two different skips, and the second is the one that surprises people.

lame version 3.100 already built. Remove workspace/.stamps/lame-3.100 to rebuild.

That one says what to do. This one does not:

x264 is outdated but will not be rebuilt. Use --rebuild-outdated to rebuild.

It means a stamp exists for a different version than the recipe now wants — after a version bump, a profile switch, or an upstream pin moving. The recipe is skipped and the build continues with the old library. Nothing fails. Either pass --rebuild-outdated, or delete the stale stamp yourself.

"refusing to produce a mixed-level workspace"

[mediaforge] WARNING: This workspace was built at debug level 'none'; you asked for 'full'.
[mediaforge] WARNING: Build stamps record only name and version, so the already-built recipes
[mediaforge] WARNING: would NOT be rebuilt and the result would mix the two levels silently.
[mediaforge] FATAL: refusing to produce a mixed-level workspace

This is working as intended, and it is protecting you. Stamps key on name and version alone, so nothing about them records the debug level. Without this refusal a second build at a different level would skip every recipe it had already built and link a debug FFmpeg against optimized, stripped archives — which looks like a successful debug build and is not one.

The level is recorded in workspace/.debug-level. To change it, rebuild:

./mediaforge.sh clean          # or: rm -rf workspace/.stamps
./mediaforge.sh build --debug=symbols

The debugger stopped working, but the binary still runs

Symptom: ffmpeg runs normally, and gdb says

During symbol reading: Could not find DWO CU libavcodec/packet.dwo(0x7d59b7a8e3be672d)
  referenced by CU at offset 0x16df1 [in module /home/you/.local/mediaforge/bin/ffmpeg]
warning: Could not find DWO CU ...
No breakpoints, watchpoints, tracepoints, or catchpoints.

That last line is the damage: the breakpoint was not set, and gdb continued without failing. Reproduced by hiding one .dwo file and re-running gdb against an otherwise untouched prefix.

The cause is that a --debug build splits its debug info into .dwo files beside the objects under packages/, and those are never installed. Something removed or replaced them:

  • ./mediaforge.sh clean — it warns first, but it does remove them.
  • You copied the prefix to another machine without packages/.
  • You rebuilt a recipe, so its objects and .dwo files were replaced while binaries linked against the old archive still reference the old ones.

There is no repair short of rebuilding at the same level. Function names still resolve in a backtrace, because the skeleton stays in the object; it is source-level stepping, locals and macros that go.

See Debug builds and split DWARF for what the split buys and why it is on by default.

.o.d: No such file or directory during a cmake build

Looks like a missing dependency file in a cmake-generated makefile. It is contention, not a defect — a parallel-make race that shows up when the machine is oversubscribed, typically with orphaned build processes from an earlier interrupted run still consuming cores.

ps aux | grep -E '[c]make|[m]ake|[c]c1'   # look for orphans from a previous run

Reap those, remove the package's extracted tree so it re-extracts clean, and rebuild. Lowering -j makes it less likely.

"gcc is unable to create an executable file"

Usually a missing static system library, and almost always during --enable-static. The specific missing symbol is in the package's own config.log, not in mediaforge's output. See the static-build section of BUILDING.md for the per-distribution package list — on Arch in particular the official packages ship no .a files at all.

"pkg-config: not found"

mediaforge builds its own pkg-config before anything consumes it. If that recipe failed, the cause is upstream of everything else — check that make and a working compiler are present, and read workspace/.logs/pkg-config-*.log.

When the tree is confused enough to start over

./mediaforge.sh clean          # build tree + unpacked sources; keeps downloads
./mediaforge.sh build --enable-nonfree

clean deliberately keeps the verified tarballs and git clones. Re-downloading and re-verifying ~110 archives to fix a build problem is rarely what you want — clean --all does that, and names what it is about to remove first.

Checking a build you already have

./mediaforge.sh reconcile          # do the stamps still match the workspace?
./mediaforge.sh check-shadowers    # would any .pc shadow the system's?

reconcile exits 1 if a stamp has lost the artifacts it vouches for — a build claiming to have produced something the workspace no longer contains. --prune drops those stamps so the next build redoes them. Note that a small number of recipes install nothing at all and report as unverifiable rather than as drift; that is the difference between no evidence and evidence of a problem.

Reporting it

Include the mediaforge command line, the failing recipe, and the log the run names. A build that fails inside a dependency usually fails the same way outside mediaforge — say whether you tried it.

See also