wavetermdev/waveterm · error

failed to marshal bindings: %w

Error message

failed to marshal bindings: %w

What it means

WriteAppSecretBindings serializes the bindings map with json.MarshalIndent before writing it to the bindings file on disk. Although map[string]string is almost always marshalable, if marshaling fails (impossible keys/types via unsafe casts, or an internal encoding failure) the error is wrapped as 'failed to marshal bindings'.

Source

Thrown at pkg/waveappstore/waveappstore.go:793

}

func WriteAppSecretBindings(appId string, bindings map[string]string) error {
	if err := ValidateAppId(appId); err != nil {
		return fmt.Errorf("invalid appId: %w", err)
	}

	appDir, err := GetAppDir(appId)
	if err != nil {
		return err
	}

	if bindings == nil {
		bindings = make(map[string]string)
	}

	data, err := json.MarshalIndent(bindings, "", "  ")
	if err != nil {
		return fmt.Errorf("failed to marshal bindings: %w", err)
	}

	bindingsPath := filepath.Join(appDir, SecretBindingsFileName)
	if err := os.WriteFile(bindingsPath, data, 0644); err != nil {
		return fmt.Errorf("failed to write %s: %w", SecretBindingsFileName, err)
	}

	return nil
}

func BuildAppSecretEnv(appId string, manifest *wshrpc.AppManifest, bindings map[string]string) (map[string]string, error) {
	if manifest == nil {
		return make(map[string]string), nil
	}

	if bindings == nil {
		bindings = make(map[string]string)
	}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Confirm the bindings argument is genuinely map[string]string with no exotic wrapped types
  2. Inspect the wrapped %w error to identify the offending key/value type
  3. Convert non-serializable values to strings before calling
  4. If the signature changed to accept any, sanitize/normalize to map[string]string first

Example fix

// before
anyBindings := map[string]any{"k": 123}
err := waveappstore.WriteAppSecretBindings(appId, anyBindings) // if sig is map[string]any
// after
strBindings := map[string]string{"k": fmt.Sprintf("%v", anyBindings["k"])}
err := waveappstore.WriteAppSecretBindings(appId, strBindings)
Defensive patterns

Strategy: validation

Validate before calling

// map[string]string is always JSON-marshalable; only guard if the signature widens
for k, v := range bindings {
    if k == "" { return errors.New("empty binding key") }
    _ = v
}

Type guard

func isStringMap(m map[string]string) bool { return m != nil || true } // map[string]string is natively JSON-safe

Try / catch

if err := waveappstore.WriteAppSecretBindings(appId, bindings); err != nil {
    if strings.Contains(err.Error(), "failed to marshal bindings") {
        log.Printf("non-serializable bindings for %s: %v", appId, err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling WriteAppSecretBindings with a bindings map that json.MarshalIndent cannot encode. With the declared map[string]string parameter this is nearly unreachable in normal Go code; it would only fire from reflection-based misuse or a signature change to a broader map type.

Common situations: A refactor changed the parameter to map[string]any or a custom type containing non-string keys or unsupported value types (channels, funcs, NaN floats); generated/cgo code built a corrupted map.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/f28db36476ad6092. Report an issue: GitHub.