{"record":{"id":"b51a08d3d8ceeaca","repo":"rust-lang/mdBook","slug":"theme-dir-does-not-exist","errorCode":null,"errorMessage":"theme dir {} does not exist","messagePattern":"theme dir (.+?) does not exist","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/mdbook-html/src/html_handlebars/hbs_renderer.rs","lineNumber":328,"sourceCode":"        let html_config = ctx.config.html_config().unwrap_or_default();\n        let src_dir = ctx.root.join(&ctx.config.book.src);\n        let destination = &ctx.destination;\n        let book = &ctx.book;\n        let build_dir = ctx.root.join(&ctx.config.build.build_dir);\n\n        if destination.exists() {\n            fs::remove_dir_content(destination)\n                .with_context(|| \"Unable to remove stale HTML output\")?;\n        }\n\n        trace!(\"render\");\n        let mut handlebars = Handlebars::new();\n\n        let theme_dir = match html_config.theme {\n            Some(ref theme) => {\n                let dir = ctx.root.join(theme);\n                if !dir.is_dir() {\n                    bail!(\"theme dir {} does not exist\", dir.display());\n                }\n                dir\n            }\n            None => ctx.root.join(\"theme\"),\n        };\n\n        let theme = Theme::new(theme_dir);\n\n        debug!(\"Register the index handlebars template\");\n        handlebars.register_template_string(\"index\", String::from_utf8(theme.index.clone())?)?;\n\n        debug!(\"Register the head handlebars template\");\n        handlebars.register_partial(\"head\", String::from_utf8(theme.head.clone())?)?;\n\n        debug!(\"Register the redirect handlebars template\");\n        handlebars\n            .register_template_string(\"redirect\", String::from_utf8(theme.redirect.clone())?)?;\n","sourceCodeStart":310,"sourceCodeEnd":346,"githubUrl":"https://github.com/rust-lang/mdBook/blob/dc21064fc21d955a0e1f67e65e336883c3e5260b/crates/mdbook-html/src/html_handlebars/hbs_renderer.rs#L310-L346","documentation":"When output.html.theme is set in book.toml, mdBook joins that path against the book root and requires it to be an existing directory containing custom theme files. If the configured directory doesn't exist, rendering aborts with this error so the user notices a bad theme path instead of silently using defaults.","triggerScenarios":"Calling MdBook::load/build with [output.html] theme = \"path\" where root.join(path) is not a directory: typo in the path, path relative to the wrong directory, or the theme directory was deleted/moved before running mdbook build.","commonSituations":"Cloning a book repo where the custom theme dir wasn't committed (e.g. ignored by .gitignore); renaming the theme folder; running mdbook from a different working directory than expected.","solutions":["Create the configured theme directory or fix the path in book.toml so it points at an existing directory relative to the book root.","Remove the `theme = ...` line from [output.html] to fall back to the default theme (or the built-in theme dir).","Run `mdbook theme` (or copy the default theme out) to scaffold the theme directory, then customize it."],"exampleFix":"// before (book.toml)\n[output.html]\ntheme = \"./my-them\"\n\n// after\n[output.html]\ntheme = \"./my-theme\"","handlingStrategy":"validation","validationCode":"// Before invoking mdbook\nconst theme = config['output.html.theme'];\nif (theme && !fs.existsSync(path.join(bookRoot, theme))) {\n  throw new Error(`theme dir missing: ${path.join(bookRoot, theme)}`);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Commit the custom theme directory to version control.","Verify theme paths are relative to the book root (where book.toml lives).","Run a pre-build check that all configured directories exist."],"tags":["config","theme","filesystem","mdbook"],"backgroundTag":"missing-directory","analyzedSha":"dc21064fc21d955a0e1f67e65e336883c3e5260b","analyzedAt":"2026-09-01T10:15:12.134Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}