Skip to content

Encoder.SetIndent panics on negative input — undocumented, opportunity to return error before v4 stable #323

@quocvibui

Description

@quocvibui

Summary

Encoder.SetIndent panics when called with a negative number of spaces. The doc comment does not mention this panic, so callers have no way to discover this behavior without reading the source. Since v4 is still a release candidate, this is a good time to consider returning an error instead.

Reproduction

Confirmed on go.yaml.in/yaml/v4 v4.0.0-rc.4, Go 1.25.1, darwin/arm64.

package main

import (
    "bytes"
    "go.yaml.in/yaml/v4"
)

func main() {
    var buf bytes.Buffer
    enc := yaml.NewEncoder(&buf)
    enc.SetIndent(-1)
    // panic: yaml: cannot indent to a negative number of spaces
}

Current Source (yaml.go ~line 547)

// SetIndent changes the used indentation used when encoding.
func (e *Encoder) SetIndent(spaces int) {
    if spaces < 0 {
        panic("yaml: cannot indent to a negative number of spaces")
    }
    e.encoder.Indent = spaces
}

The doc comment says only "SetIndent changes the used indentation used when encoding." — no mention of panic behavior.

Why This Matters

  • Downstream impact already observed. The yq tool has mikefarah/yq#2329 where yq -I=-1 produces a raw panic stacktrace because the value is passed through to SetIndent. End users see a crash instead of a meaningful error.
  • If spaces comes from user input, configuration, or computation, a negative value crashes the entire program with no opportunity for the caller to handle it gracefully.
  • The Go standard library is inconsistent here — text/tabwriter.Init panics on negative values (also undocumented), but encoding/json.Encoder.SetIndent does no validation at all. Neither is ideal; returning an error is the most composable option for a library.

Suggested Fix

Since v4 has not yet reached stable, the signature can still change without breaking semver:

Option A — Return an error (preferred):

func (e *Encoder) SetIndent(spaces int) error {
    if spaces < 0 {
        return fmt.Errorf("yaml: cannot indent to a negative number of spaces")
    }
    e.encoder.Indent = spaces
    return nil
}

Option B — Clamp to zero:

func (e *Encoder) SetIndent(spaces int) {
    if spaces < 0 {
        spaces = 0
    }
    e.encoder.Indent = spaces
}

Option C — At minimum, document the panic:

// SetIndent changes the used indentation used when encoding.
// It panics if spaces is negative.
func (e *Encoder) SetIndent(spaces int) {

Related

Environment

  • yaml version: go.yaml.in/yaml/v4 v4.0.0-rc.4
  • Go version: go1.25.1 darwin/arm64

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions