hashicorp/nomad · error

%v

Error message

%v

What it means

While generating the HTML index for the debug bundle, template parsing errors are silently discarded with `head, _ :=` / `line, _ :=`, and then a stale `err` (from an earlier statement, e.g. creating the HTML file) is re-checked and wrapped with `%v`. The template parses shown always succeed, so this error surfaces only when the earlier file-creation step failed, and the message loses the error's type (unwrapped via %v).

Solutions

  1. Look at the stringified message body for the underlying OS error (path, permission, or ENOSPC)
  2. Ensure the -output directory for the debug bundle exists and is writable
  3. Free disk space if the message indicates a full filesystem
  4. Fix the code to check err immediately after creating htmlFh and wrap with %w instead of %v to preserve the cause

Example fix

// before
head, _ := template.New("head").Parse(...)
line, _ := template.New("line").Parse(...)
if err != nil {
    return fmt.Errorf("%v", err)
}
// after
fh, err := os.Create(...)
if err != nil {
    return fmt.Errorf("failed to create html file: %w", err)
}
head, err := template.New("head").Parse(...)
if err != nil {
    return fmt.Errorf("failed to parse head template: %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

// before generating the bundle index, verify the html file was created
fh, err := os.Create(htmlPath)
if err != nil {
    return fmt.Errorf("create html index: %w", err)
}
// and validate templates eagerly
if _, err := template.New("head").Parse(headTmpl); err != nil {
    return fmt.Errorf("bad head template: %w", err)
}

Try / catch

if err := generateIndex(htmlFh, c); err != nil {
    log.Printf("debug bundle index generation failed: %v", err)
    // inspect inner OS error for the real filesystem cause
}

Prevention

When it happens

Trigger: The `err` variable left over from creating/opening the HTML output file (htmlFh) is non-nil when control reaches the check after the template.Parse calls, producing fmt.Errorf("%v", err).

Common situations: `nomad operator debug` cannot create its HTML index file because the output directory is missing, unwritable, or the disk is full; the real cause is hidden because the error is stringified, not wrapped.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/489c13ae5bd0a5b5. Report an issue: GitHub.

Appendix: source

Thrown at command/operator_debug.go:1735

	if err != nil {
		return err
	}
	defer jsonFh.Close()

	json.NewEncoder(jsonFh).Encode(c.manifest)

	// Write the HTML
	path = filepath.Join(c.collectDir, "index.html")
	htmlFh, err := os.Create(path)
	if err != nil {
		return err
	}
	defer htmlFh.Close()

	head, _ := template.New("head").Parse("<html><head><title>{{.}}</title></head>\n<body><h1>{{.}}</h1>\n<ul>")
	line, _ := template.New("line").Parse("<li><a href=\"{{.}}\">{{.}}</a></li>\n")
	if err != nil {
		return fmt.Errorf("%v", err)
	}
	tail := "</ul></body></html>\n"

	head.Execute(htmlFh, c.timestamp)
	for _, f := range c.manifest {
		line.Execute(htmlFh, f)
	}
	htmlFh.WriteString(tail)

	return nil
}

// trap captures signals, and closes stopCh
func (c *OperatorDebugCommand) trap() {
	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh,
		syscall.SIGHUP,
		syscall.SIGINT,

View on GitHub (pinned to 482b49bf1a)