{"record":{"id":"3b78f22de53adbda","repo":"AdguardTeam/AdGuardHome","slug":"getting-embedded-client-subdir-w","errorCode":null,"errorMessage":"getting embedded client subdir: %w","messagePattern":"getting embedded client subdir: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/home/home.go","lineNumber":690,"sourceCode":"\t// isFirstRun defines if current run is the first run.\n\tisFirstRun bool\n}\n\n// newWeb initializes the web module.  conf must not be nil.\nfunc newWeb(ctx context.Context, conf *webConfig) (web *webAPI, err error) {\n\tlogger := conf.baseLogger.With(slogutil.KeyPrefix, \"webapi\")\n\n\twebPort := suggestedWebPort(ctx, logger)\n\n\tvar clientFS fs.FS\n\tif conf.opts.localFrontend {\n\t\tlogger.WarnContext(ctx, \"using local frontend files\")\n\n\t\tclientFS = os.DirFS(\"build/static\")\n\t} else {\n\t\tclientFS, err = fs.Sub(conf.clientBuildFS, \"build/static\")\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"getting embedded client subdir: %w\", err)\n\t\t}\n\t}\n\n\tdisableUpdate := !isUpdateEnabled(ctx, conf.baseLogger, &conf.opts, conf.isCustomUpdURL)\n\n\twebConf := &webAPIConfig{\n\t\tCommandConstructor: executil.SystemCommandConstructor{},\n\t\tupdater:            conf.updater,\n\t\tlogger:             logger,\n\t\tbaseLogger:         conf.baseLogger,\n\t\tconfModifier:       conf.configModifier,\n\t\thttpReg:            conf.httpReg,\n\t\ttlsManager:         conf.tlsManager,\n\t\tauth:               conf.auth,\n\t\tmux:                conf.mux,\n\t\thostsContainer:     conf.hostsContainer,\n\n\t\tclientFS: clientFS,","sourceCodeStart":672,"sourceCodeEnd":708,"githubUrl":"https://github.com/AdguardTeam/AdGuardHome/blob/b41aefbe51c8dde65e2c50f093996afa0502edf9/internal/home/home.go#L672-L708","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before: built without frontend\ngo build ./\n\n// after: build frontend then embed\ncd frontend && yarn && yarn build\ncd .. && go build ./","handlingStrategy":"validation","validationCode":"// Before running, verify embedded assets exist in your build:\nif _, err := fs.Sub(clientBuildFS, \"build/static\"); err != nil {\n    log.Fatal(\"frontend assets missing; rebuild with ./scripts/make\")\n}","typeGuard":null,"tryCatchPattern":"if err := run(ctx); err != nil {\n    if strings.Contains(err.Error(), \"getting embedded client subdir\") {\n        log.Fatalf(\"frontend not embedded: %v — rebuild with the frontend step\", err)\n    }\n    log.Fatal(err)\n}","preventionTips":["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"],"tags":["go","embedded-assets","frontend","startup","fs-sub"],"backgroundTag":"embedded-fs-path-missing","analyzedSha":"b41aefbe51c8dde65e2c50f093996afa0502edf9","analyzedAt":"2026-08-27T04:57:55.097Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}