hashicorp/nomad · error

failed to convert %q to a log index: %v

Error message

failed to convert %q to a log index: %v

What it means

logIndexes parses log file names of the form <task>.<stdout|stderr>.<index> in the alloc's log directory. When the extracted index component cannot be parsed as an integer with strconv.Atoi, it returns this error, aborting the listing. A malformed filename in the log directory causes the whole log request to fail.

Source

Thrown at client/fs_endpoint.go:892

// error is returned.
func logIndexes(entries []*cstructs.AllocFileInfo, task, logType string) (indexTupleArray, error) {
	var indexes []indexTuple
	prefix := fmt.Sprintf("%s.%s.", task, logType)
	for _, entry := range entries {
		if entry.IsDir {
			continue
		}

		// If nothing was trimmed, then it is not a match
		idxStr := strings.TrimPrefix(entry.Name, prefix)
		if idxStr == entry.Name {
			continue
		}

		// Convert to an int
		idx, err := strconv.Atoi(idxStr)
		if err != nil {
			return nil, fmt.Errorf("failed to convert %q to a log index: %v", idxStr, err)
		}

		indexes = append(indexes, indexTuple{idx: int64(idx), entry: entry})
	}

	return indexTupleArray(indexes), nil
}

// notFoundErr is returned when a log is requested but cannot be found.
// Implements agent.HTTPCodedError but does not reference it to avoid circular
// imports.
type notFoundErr struct {
	taskName string
	logType  string
}

func (e notFoundErr) Error() string {
	return fmt.Sprintf("log entry for task %q and log type %q not found", e.taskName, e.logType)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Remove or relocate non-Nomad files (e.g. *.bak, *.tmp) from the alloc's /alloc/logs directory.
  2. Configure the task to write its own output elsewhere (task's own dir, not /alloc/logs).
  3. Check for symlinks or copies in the log dir created by backup/collector tooling and exclude them.
  4. If caused by a Nomad version mismatch, ensure client and server versions are compatible.

Example fix

// before
# task writes diagnostics into /alloc/logs
command = "myapp > /alloc/logs/web.stdout.0.txt 2>&1"
// after
# write task output outside the Nomad log dir
command = "myapp > /local/myapp.log 2>&1"
Defensive patterns

Strategy: validation

Validate before calling

entries, _, err := client.AllocFS().List(alloc, "/alloc/logs", nil)
if err != nil {
    return err
}
re := regexp.MustCompile(`^[^.]+\.(stdout|stderr)\.\d+$`)
for _, e := range entries {
    if !re.MatchString(e.Name) {
        return fmt.Errorf("unexpected file in log dir: %s", e.Name)
    }
}

Type guard

func isIndexParseErr(err error) bool {
    return strings.Contains(err.Error(), "to a log index")
}

Try / catch

if err := readLogs(); err != nil {
    if isIndexParseErr(err) {
        return fmt.Errorf("clean non-Nomad files from /alloc/logs and retry")
    }
    return err
}

Prevention

When it happens

Trigger: A file in the alloc log directory whose name has a non-numeric index segment — files created by user tasks or external processes writing into /alloc/logs, or corrupted/renamed Nomad log files.

Common situations: Tasks writing their own files into the shared /alloc/logs directory with arbitrary names; tooling symlinks or backups like web.stdout.0.bak; manual copies of log files with altered names; older Nomad versions producing different naming schemes.

Related errors


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