slimtoolkit/slim · error

could not decode command %q: %w

Error message

could not decode command %q: %w

What it means

After reading the first line of the command file, readCommandFile unmarshals it into a command.StartMonitor struct. If the JSON is malformed or does not match the struct, this error wraps the json.Unmarshal failure, echoing the offending data.

Source

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

	}

	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:
	//
	// ENTRYPOINT ["/path/to/sensor", "-m=standalone", "-c=/path/to/commands.json", "--" ]

	// Note on CMD & ENTRYPOINT override: Historically, sensor used
	// AppName + AppArgs[] to start the target process. With the addition
	// of the standalone mode, the need for supporting Docker's original

View on GitHub (pinned to 81940d17fa)

Solutions

  1. Inspect the echoed data in the error and validate it as JSON (e.g. jq) to find the syntax/schema problem.
  2. Ensure the instrumentor and sensor use compatible versions of the command.StartMonitor schema.
  3. Regenerate the command file with the correct JSON StartMonitor payload as its first line.

Example fix

// before (malformed first line)
{"command":, "args":[]}
// after (valid StartMonitor JSON)
{"command":"/usr/bin/app","args":["--port","8080"]}
Defensive patterns

Strategy: validation

Validate before calling

func validateCommandFile(path string) error {
    data, err := os.ReadFile(path)
    if err != nil { return err }
    first := bytes.Split(data, []byte("\n"))[0]
    var probe map[string]interface{}
    return json.Unmarshal(first, &probe)
}

Type guard

func isJSONDecodeError(err error) bool {
    var ue *json.UnmarshalTypeError
    var se *json.SyntaxError
    return errors.As(err, &ue) || errors.As(err, &se)
}

Try / catch

exec, err := execution.NewStandalone(commandFile, eventFile, hook)
if err != nil && strings.Contains(err.Error(), "could not decode command") {
    log.Fatalf("command file contains invalid JSON: %v", err)
}

Prevention

When it happens

Trigger: Command file's first line is empty, truncated, contains invalid JSON, or has fields incompatible with command.StartMonitor (wrong types, unknown/mismatched schema).

Common situations: Instrumentor wrote a partial/older schema version of the command; file corrupted on write; the first line is a shell shebang or comment instead of JSON.

Related errors


AI-assisted analysis of slimtoolkit/slim@81940d17fa (2026-08-31). Data as JSON: /api/errors/46708440c81a3e56. Report an issue: GitHub.