{"record":{"id":"58dcbe4ed84f7889","repo":"gohugoio/hugo","slug":"publishdir-is-empty","errorCode":null,"errorMessage":"publishDir is empty","messagePattern":"publishDir is empty","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"hugofs/fs.go","lineNumber":101,"sourceCode":"// NewFromSourceAndDestination creates a new Fs based on the provided Afero Fss\n// as the source and destination file systems.\nfunc NewFromSourceAndDestination(source, destination afero.Fs, cfg config.Provider) *Fs {\n\tworkingDir, publishDir := getWorkingPublishDir(cfg)\n\treturn newFs(source, destination, workingDir, publishDir)\n}\n\nfunc getWorkingPublishDir(cfg config.Provider) (string, string) {\n\tworkingDir := cfg.GetString(\"workingDir\")\n\tpublishDir := cfg.GetString(\"publishDirDynamic\")\n\tif publishDir == \"\" {\n\t\tpublishDir = cfg.GetString(\"publishDir\")\n\t}\n\treturn workingDir, publishDir\n}\n\nfunc newFs(source, destination afero.Fs, workingDir, publishDir string) *Fs {\n\tif publishDir == \"\" {\n\t\tpanic(\"publishDir is empty\")\n\t}\n\n\tif workingDir == \".\" {\n\t\tworkingDir = \"\"\n\t}\n\n\t// Sanity check\n\tif IsOsFs(source) && len(workingDir) < 2 {\n\t\tpanic(\"workingDir is too short\")\n\t}\n\n\t// If this does not exist, it will be created later.\n\tabsPublishDir := paths.AbsPathify(workingDir, publishDir)\n\n\tpubFs := NewBasePathFs(destination, absPublishDir)\n\n\treturn &Fs{\n\t\tSource:             source,","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/hugofs/fs.go#L83-L119","documentation":"A panic in newFs (hugofs/fs.go:101) when publishDir is empty. Hugo requires a concrete output directory to write rendered files; publishDir is sourced from config keys publishDirDynamic then publishDir (default 'public').","triggerScenarios":"Configuring Hugo (or constructing hugofs) with both publishDirDynamic and publishDir unset/empty; calling hugofs.NewFrom with BaseConfig.PublishDir empty.","commonSituations":"Programmatically building Hugo's config without a publish directory; tests that forget to set PublishDir; a config file blanketing publishDir with an empty string.","solutions":["Set publishDir in config (Hugo's default is 'public')","When using hugofs.NewFrom, ensure conf.PublishDir is non-empty","Check hugo.toml/command-line flags are not overriding publishDir with ''"],"exampleFix":"// before\ncfg := config.BaseConfig{WorkingDir: \"/proj\"}\nfs := hugofs.NewFrom(memFs, cfg)\n// after\ncfg := config.BaseConfig{WorkingDir: \"/proj\", PublishDir: \"public\"}\nfs := hugofs.NewFrom(memFs, cfg)","handlingStrategy":"validation","validationCode":"if publishDir == \"\" {\n    return nil, errors.New(\"publishDir must be set (default 'public')\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set PublishDir when building hugofs config programmatically","Keep the default 'public' unless you have a reason to change it","Unit-test Fs construction with a non-empty publish dir"],"tags":["config","filesystem","panic","hugofs"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}