slimtoolkit/slim · error

could not read command file %q: %w

Error message

could not read command file %q: %w

What it means

readCommandFile loads the command file with os.ReadFile and returns the first line. If reading the file fails at the OS level (file absent, permission denied, path is a directory), this error wraps the os.ReadFile failure and is returned to NewStandalone.

Source

Thrown at pkg/app/sensor/execution/standalone.go:101

	encoder := json.NewEncoder(e.eventFile)
	encoder.SetEscapeHTML(false)
	evt := event.Message{Name: name}
	if len(data) > 0 {
		evt.Data = data[0]
	}

	if err := encoder.Encode(evt); err != nil {
		log.WithError(err).Warn("sensor: failed dumping event")
	}
}

// TODO: Make this function return a list of commands.
func readCommandFile(filename string) (command.StartMonitor, error) {
	var cmd command.StartMonitor

	data, err := os.ReadFile(filename)
	if err != nil {
		return cmd, fmt.Errorf("could not read command file %q: %w", filename, err)
	}
	data = bytes.Split(data, []byte("\n"))[0]

	if err := json.Unmarshal(data, &cmd); err != nil {
		return cmd, fmt.Errorf("could not decode command %q: %w", string(data), err)
	}

	// The instrumented image will always have the ENTRYPOINT overwritten
	// by the instrumentor to make the sensor the PID1 process in the monitored
	// container.
	// The original ENTRYPOINT & CMD will be preserved as part of the
	// `commands.json` file. However, it's also possible to override the
	// CMD at runtime by supplying extra args to the `docker run` (or alike)
	// command. Sensor needs to be able to detect this and replace the
	// baked in CMD with the new list of args. For that, the instrumented image's
	// ENTRYPOINT has to contain a special separator value `--` denoting the end
	// of the sensor's flags sequence. Example:
	//

View on GitHub (pinned to 81940d17fa)

Solutions

  1. Confirm the command file exists at the exact path (check the wrapped ENOENT/EPERM error).
  2. Add ordering/retry so the sensor only starts after the command file has been written.
  3. Correct the command file path in the execution setup configuration.

Example fix

// before
cmd, err := readCommandFile(cfg.CommandFile) // ENOENT
// after
if _, err := os.Stat(cfg.CommandFile); err != nil {
    return nil, fmt.Errorf("command file not present yet: %w", err)
}
cmd, err := readCommandFile(cfg.CommandFile)
Defensive patterns

Strategy: validation

Validate before calling

func waitForFile(path string, timeout time.Duration) error {
    deadline := time.Now().Add(timeout)
    for time.Now().Before(deadline) {
        if fi, err := os.Stat(path); err == nil && fi.Size() > 0 {
            return nil
        }
        time.Sleep(100 * time.Millisecond)
    }
    return fmt.Errorf("command file %s not ready within %s", path, timeout)
}

Type guard

func isReadFailure(err error) bool {
    return errors.Is(err, fs.ErrNotExist) || errors.Is(err, fs.ErrPermission)
}

Try / catch

cmd, err := readCommandFile(filename) // via NewStandalone
if err != nil && strings.Contains(err.Error(), "could not read command file") {
    // retry after checking the file exists, or fail startup with a clear message
    return retryOrAbort(fmt.Errorf("command file unreadable: %w", err))
}

Prevention

When it happens

Trigger: readCommandFile called with a filename that cannot be opened for reading: nonexistent path, wrong permissions, or path resolves to a directory.

Common situations: Sensor started before the orchestrator/instrumentor wrote the command file (race condition); command file path misconfigured; shared emptyDir volume not mounted.

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 slimtoolkit/slim@81940d17fa (2026-08-31). Data as JSON: /api/errors/01ad4d45e89d3826. Report an issue: GitHub.