mikefarah/yq · error
cannot encode %v as URI, can only operate on strings. Please
Error message
cannot encode %v as URI, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string
What it means
The sh (shell quoting) encoder can only serialize string nodes. It checks `node.guessTagFromCustomType() != "!!str"` and rejects anything else (ints, bools, maps, seqs) telling you to convert the value to a string first. The message mentions URI because the sh encoder is shared with the URI output path.
Source
Thrown at pkg/yqlib/encoder_sh.go:36
func NewShEncoder() Encoder {
return &shEncoder{false}
}
func (e *shEncoder) CanHandleAliases() bool {
return false
}
func (e *shEncoder) PrintDocumentSeparator(_ io.Writer) error {
return nil
}
func (e *shEncoder) PrintLeadingContent(_ io.Writer, _ string) error {
return nil
}
func (e *shEncoder) Encode(writer io.Writer, node *CandidateNode) error {
if node.guessTagFromCustomType() != "!!str" {
return fmt.Errorf("cannot encode %v as URI, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag)
}
return writeString(writer, e.encode(node.Value))
}
// put any (shell-unsafe) characters into a single-quoted block, close the block lazily
func (e *shEncoder) encode(input string) string {
const quote = '\''
var inQuoteBlock = false
var encoded strings.Builder
encoded.Grow(len(input))
for _, ir := range input {
// open or close a single-quote block
if ir == quote {
if inQuoteBlock {
// get out of a quote block for an input quote
encoded.WriteRune(quote)View on GitHub (pinned to 8b5af0694b)
Solutions
- Force string conversion: `yq -o sh '.count | tostring' file.yaml`.
- Or retag: `yq -o sh '.count tag="!!str"' file.yaml`.
- For multiple values, map over them: `yq -o sh '.[] | tostring'`.
- Quote in the YAML source (`count: "123"`) if the value is inherently textual.
Example fix
# before yq -o sh '.port' config.yaml # port: 8080 (!!int) -> error # after yq -o sh '.port | tostring' config.yaml
Defensive patterns
Strategy: type-guard
Validate before calling
[ "$(yq '.port | tag' config.yaml)" = "!!str" ] || echo "pipe through tostring"
Type guard
isStringNode() { [ "$(yq "$1" | yq 'tag')" = "!!str" ]; } Try / catch
val=$(yq -o sh '.port | tostring' config.yaml) || val=$(yq -o sh '.port' config.yaml)
Prevention
- Always append `| tostring` when exporting values to -o sh
- Quote inherently-textual values in the YAML source
- Remember YAML auto-typing: 123, true, null are not strings
When it happens
Trigger: `yq -o sh '.count' file.yaml` where `.count` is `!!int`; piping a boolean/null node to `-o sh`; encoding a map/sequence node with `-o sh`/`@uri`.
Common situations: Exporting numeric env vars for `eval` in shell scripts; quoting timestamps or booleans for shell; forgetting YAML auto-typing turns `true`, `123`, `null` into non-string tags.
Related errors
- unsupported node %v
- cannot encode %v as URI, can only operate on strings. Please
- cannot encode %v to XML - only maps can be encoded
- cannot use %v as attribute, only scalars are supported
- no support for output format
AI-assisted analysis of mikefarah/yq@8b5af0694b (2026-09-05).
Data as JSON: /api/errors/a2740a07a72394cb.
Report an issue: GitHub.