gastownhall/beads · error

failed to encode config.yaml: %w

Error message

failed to encode config.yaml: %w

What it means

SetReposInYAML re-encodes the modified yaml.Node tree via a yaml.Encoder. If Encode fails (rare — usually only from invalid node contents such as a nil/invalid node in the tree), the error is wrapped as "failed to encode config.yaml".

Source

Thrown at internal/config/repos.go:144

			// Remove repos section entirely if empty
			mapping.Content = append(mapping.Content[:reposIndex], mapping.Content[reposIndex+2:]...)
		} else {
			mapping.Content[reposIndex+1] = reposNode
		}
	} else if reposNode != nil {
		// Add new repos section at the end
		mapping.Content = append(mapping.Content,
			&yaml.Node{Kind: yaml.ScalarNode, Value: "repos"},
			reposNode,
		)
	}

	// Marshal back to YAML
	var buf strings.Builder
	encoder := yaml.NewEncoder(&buf)
	encoder.SetIndent(2)
	if err := encoder.Encode(&root); err != nil {
		return fmt.Errorf("failed to encode config.yaml: %w", err)
	}
	if err := encoder.Close(); err != nil {
		return fmt.Errorf("failed to close encoder: %w", err)
	}

	// Write back to file
	if err := os.WriteFile(configPath, []byte(buf.String()), 0600); err != nil {
		return fmt.Errorf("failed to write config.yaml: %w", err)
	}

	// Reload viper config so changes take effect immediately
	if v != nil {
		if err := v.ReadInConfig(); err != nil {
			// Not fatal - config is on disk, will be picked up on next command
			_ = err // Best effort: viper reload failure is non-fatal since config was already written to disk
		}
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the code that builds/mutates the yaml.Node tree for zero-value nodes (Kind must be set)
  2. Ensure all nodes appended carry a valid Kind, Style, and Value/Content
  3. Upgrade gopkg.in/yaml.v3 — some encode bugs were fixed in later versions
  4. If reproducible, marshal a plain struct instead of a Node tree to isolate the bad value

Example fix

// before
node := yaml.Node{} // Kind not set -> encode error
// after
node := yaml.Node{Kind: yaml.ScalarNode, Value: repoPath}
Defensive patterns

Strategy: try-catch

Try / catch

if err := SetReposInYAML(cfgPath, repos); err != nil {
    if strings.Contains(err.Error(), "failed to encode") {
        log.Printf("node tree invalid, update yaml.v3: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: encoder.Encode(&root) returns an error, typically from an invalid yaml.Node value inserted into the tree (e.g. zero-value nodes with Kind 0) or an unencodable value.

Common situations: A custom build or patched config-construction code injected an invalid node; running against a corrupted in-memory tree rather than a user mistake in most cases.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/922ca43ec7fb47f6. Report an issue: GitHub.