hashicorp/nomad · error

error reading %q: %s

Error message

error reading %q: %s

What it means

readPathFromArgs in nomad's `var put` command reads a specification file passed with the `@file` argument syntax via os.ReadFile. When the file cannot be opened or read (missing path, permission denied, path is a directory), the command aborts by wrapping the underlying OS error in `error reading %q: %s`. The %q is the path with the leading `@` stripped.

Source

Thrown at command/var_lock.go:326

		c.varPutCommand.verbose(fmt.Sprintf("Writing to path %q", path))
	}

	// Handle second argument: can @file, or child process
	args = args[1:]
	switch {
	case isArgFileRef(args[0]):
		arg := args[0]

		err = c.varPutCommand.setParserForFileArg(arg)
		if err != nil {
			return "", args, err
		}

		c.varPutCommand.verbose(fmt.Sprintf("Creating variable %q from specification file %q", path, arg))
		fPath := arg[1:]
		c.varPutCommand.contents, err = os.ReadFile(fPath)
		if err != nil {
			return "", args, fmt.Errorf("error reading %q: %s", fPath, err)
		}
		args = args[1:]
	default:
		// no-op - should be child process
	}

	return path, args, nil
}

// script returns a command to execute a script through a shell.
func script(ctx context.Context, args []string) (*exec.Cmd, error) {
	shell := "/bin/sh"

	if other := os.Getenv("SHELL"); other != "" {
		shell = other
	}

	return exec.CommandContext(ctx, shell, "-c", strings.Join(args, " ")), nil

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Verify the file exists at the exact path: `ls -l <path>` and correct any typo or run from the right directory.
  2. Check read permissions on the file (`chmod +r`) and that it is a regular file, not a directory.
  3. In CI, ensure the spec file is created/checked out before the nomad command runs (add a dependency or explicit generation step).
  4. Use an absolute path to avoid working-directory surprises.

Example fix

// before
nomad var put -path app/config @app-config.hcl
// after (file confirmed to exist first)
ls app-config.hcl && nomad var put -path app/config @./app-config.hcl
Defensive patterns

Strategy: validation

Validate before calling

if [ ! -f "${SPEC_PATH}" ]; then echo "spec file missing: ${SPEC_PATH}" >&2; exit 1; fi
[ -r "${SPEC_PATH}" ] || { echo "spec file not readable: ${SPEC_PATH}" >&2; exit 1; }

Try / catch

if err := runNomadVarPut(args...); err != nil && strings.HasPrefix(err.Error(), "error reading ") {
    // inspect wrapped *os.PathError via errors.As and report the path
    var perr *os.PathError
    if errors.As(err, &perr) { log.Fatalf("cannot read %s: %v", perr.Path, perr.Err) }
}

Prevention

When it happens

Trigger: Running `nomad var put ... @spec.json` (or `var init`-style flows) where: the spec file does not exist at fPath; the path points to a directory instead of a file; the process lacks read permission on the file; or the file was deleted between argument parsing and read time.

Common situations: Typo in the spec filename; running from a different working directory than expected; CI pipelines that forget to check out or generate the spec file; relative paths that break after `cd`; secrets files mounted with wrong permissions in containers.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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