AdguardTeam/AdGuardHome · critical
getting embedded client subdir: %w
Error message
getting embedded client subdir: %w
What it means
AdGuard Home failed to obtain the sub-filesystem 'build/static' from the embedded frontend assets via fs.Sub. This happens during newWeb when the embedded build directory structure doesn't match expectations, typically because the binary was built without the frontend assets embedded or the embed path changed between versions.
Source
Thrown at internal/home/home.go:690
// isFirstRun defines if current run is the first run.
isFirstRun bool
}
// newWeb initializes the web module. conf must not be nil.
func newWeb(ctx context.Context, conf *webConfig) (web *webAPI, err error) {
logger := conf.baseLogger.With(slogutil.KeyPrefix, "webapi")
webPort := suggestedWebPort(ctx, logger)
var clientFS fs.FS
if conf.opts.localFrontend {
logger.WarnContext(ctx, "using local frontend files")
clientFS = os.DirFS("build/static")
} else {
clientFS, err = fs.Sub(conf.clientBuildFS, "build/static")
if err != nil {
return nil, fmt.Errorf("getting embedded client subdir: %w", err)
}
}
disableUpdate := !isUpdateEnabled(ctx, conf.baseLogger, &conf.opts, conf.isCustomUpdURL)
webConf := &webAPIConfig{
CommandConstructor: executil.SystemCommandConstructor{},
updater: conf.updater,
logger: logger,
baseLogger: conf.baseLogger,
confModifier: conf.configModifier,
httpReg: conf.httpReg,
tlsManager: conf.tlsManager,
auth: conf.auth,
mux: conf.mux,
hostsContainer: conf.hostsContainer,
clientFS: clientFS,View on GitHub (pinned to b41aefbe51)
Solutions
- Rebuild the binary with the frontend: run ./scripts/make or at least the frontend build step so build/static is generated before go build
- If running from a checkout, place frontend files under build/static and run with local-frontend mode instead of relying on the embed
- Verify the embed.FS variable in internal/home still matches the 'build/static' path for your version
Example fix
// before: built without frontend go build ./ // after: build frontend then embed cd frontend && yarn && yarn build cd .. && go build ./
Defensive patterns
Strategy: validation
Validate before calling
// Before running, verify embedded assets exist in your build:
if _, err := fs.Sub(clientBuildFS, "build/static"); err != nil {
log.Fatal("frontend assets missing; rebuild with ./scripts/make")
} Try / catch
if err := run(ctx); err != nil {
if strings.Contains(err.Error(), "getting embedded client subdir") {
log.Fatalf("frontend not embedded: %v — rebuild with the frontend step", err)
}
log.Fatal(err)
} Prevention
- Always run the full build script (./scripts/make) that builds frontend before go build
- In CI, fail the pipeline if build/static is empty or absent
When it happens
Trigger: Calling run/newWeb (binary startup) when conf.clientBuildFS doesn't contain a 'build/static' directory — e.g. building with a build tag or environment that skips frontend embedding, or a corrupted/modified embed directive in internal/home.
Common situations: Custom builds from source that omit the frontend (make: skipping node build), stale embed cache after switching branches, or downstream packaging that strips embedded files.
Related errors
- starting tls manager: %w
- duplicated values: %v
- unmarshalling json data into aghalg.NullBool: bad value %q
- json duration is nil
- parsing json time: %w
AI-assisted analysis of AdguardTeam/AdGuardHome@b41aefbe51 (2026-08-27).
Data as JSON: /api/errors/3b78f22de53adbda.
Report an issue: GitHub.