mikefarah/yq · error
system operator: command must be a string scalar
Error message
system operator: command must be a string scalar
What it means
The `system` operator's resolved command must be a string scalar. resolveCommandNode throws this when the first node returned by the command expression is not a scalar, or is a scalar whose (effective) tag is not !!str — e.g. a number, boolean, map, or sequence.
Source
Thrown at pkg/yqlib/operator_system.go:53
if argsNode.Tag == "!!null" {
return nil, nil
}
if argsNode.Kind != ScalarNode {
return nil, fmt.Errorf("system operator: args must be a non-null scalar or sequence of non-null scalars; got kind=%v tag=%v", argsNode.Kind, argsNode.Tag)
}
return []string{argsNode.Value}, nil
}
func resolveCommandNode(commandNodes Context) (string, error) {
if commandNodes.MatchingNodes.Front() == nil {
return "", fmt.Errorf("system operator: command expression returned no results")
}
if commandNodes.MatchingNodes.Len() > 1 {
log.Debugf("system operator: command expression returned %d results, using first", commandNodes.MatchingNodes.Len())
}
cmdNode := commandNodes.MatchingNodes.Front().Value.(*CandidateNode)
if cmdNode.Kind != ScalarNode || cmdNode.guessTagFromCustomType() != "!!str" {
return "", fmt.Errorf("system operator: command must be a string scalar")
}
if cmdNode.Value == "" {
return "", fmt.Errorf("system operator: command must be a non-empty string")
}
return cmdNode.Value, nil
}
func systemOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
if !ConfiguredSecurityPreferences.EnableSystemOps {
return Context{}, fmt.Errorf("system operations are disabled, use --security-enable-system-operator to enable")
}
// determine at parse time whether we have (command; args) or just (command)
hasArgs := expressionNode.RHS.Operation.OperationType == blockOpType
var results = list.New()
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {View on GitHub (pinned to 8b5af0694b)
Solutions
- Point the command expression at a string field, e.g. `system(.commandString)`
- Coerce non-string scalars to a string: `system(.port | tostring)`
- Check the document tags with `yq 'path | tag'` to confirm the node is !!str
Example fix
// before: .port is !!int system(.port) // after: convert to string scalar system(.port | tostring)
Defensive patterns
Strategy: type-guard
Validate before calling
// only pass string scalars as the command system(select(tag == "!!str") | .cmd)
Type guard
// guard in expression form def isStrScalar: tag == "!!str"; .cmd | select(isStrScalar) | system(.)
Try / catch
// Go API usage
if err != nil && strings.Contains(err.Error(), "command must be a string scalar") {
// coerce or report: the selected node was not !!str
} Prevention
- Check the node tag with yq '<expr> | tag' before using it as a command
- Coerce numbers/booleans with tostring() when they should be commands
- Avoid pointing the command expression at maps or sequences
When it happens
Trigger: `system(.port)` where .port is `!!int`, `system(.enabled)` where the value is `!!bool`, or `system(.config)` where .config is a map. Also custom-typed scalars whose tag does not resolve to !!str.
Common situations: Pointing the command expression at a numeric/boolean field by mistake, or reading a command from data loaded where the tag is a custom type rather than a plain string.
Related errors
- system operator: argument must be a non-null scalar; got kin
- system operator: args must be a non-null scalar or sequence
- cannot convert node at path %v of tag %v to number
- orderedMap: invalid yaml node
- cannot multiply %v with %v
AI-assisted analysis of mikefarah/yq@8b5af0694b (2026-09-05).
Data as JSON: /api/errors/9b51e92229fb9993.
Report an issue: GitHub.