dagger/dagger · error

serialize user config: %w

Error message

serialize user config: %w

What it means

After writing a value into the TOML tree at [workspaces.<workspaceKey>], WriteUserConfigValue serializes the tree back to TOML with tree.ToTomlString(). This error wraps serialization failure — typically a value type the TOML writer cannot represent (maps with mixed types, unsupported primitives, empty map keys) inserted at the computed path.

Source

Thrown at core/workspace/userconfig.go:273

	if err != nil {
		return nil, err
	}
	tree, entryKey, err := userConfigTreeAndEntryKey(existing, workspaceKey)
	if err != nil {
		return nil, err
	}

	var value any
	if values != nil {
		value = values
	} else {
		value = parseValueString(parts, rawValue)
	}
	tree.SetPath(append([]string{"workspaces", entryKey}, parts...), value)

	out, err := tree.ToTomlString()
	if err != nil {
		return nil, fmt.Errorf("serialize user config: %w", err)
	}
	return []byte(out), nil
}

// DeleteUserConfigValue removes a config value under
// [workspaces.<workspaceKey>] in user-level config bytes, pruning any tables
// the removal leaves empty. It errors when the key is not set for that
// workspace.
func DeleteUserConfigValue(existing []byte, workspaceKey, key string) ([]byte, error) {
	parts, err := userOverlayKeyParts(key)
	if err != nil {
		return nil, err
	}
	tree, entryKey, err := userConfigTreeAndEntryKey(existing, workspaceKey)
	if err != nil {
		return nil, err
	}

View on GitHub (pinned to 82ba2681db)

Solutions

  1. Pass a scalar value (string, number, bool) or ensure the raw value parses to a TOML-compatible type
  2. Quote or normalize the workspace entry key so it forms a valid TOML table name
  3. Inspect the wrapped inner error for the offending path/type and adjust the value
  4. If writing structured data, store it as a JSON string in a settings value instead of a nested table

Example fix

// before
WriteUserConfigValue(data, key, "{a: 1}") // unparseable structure
// after
WriteUserConfigValue(data, key, "30") // scalar value serializes cleanly
Defensive patterns

Strategy: validation

Validate before calling

v := parseValueString(parts, raw)
switch v.(type) {
case string, int64, float64, bool:
default:
	return fmt.Errorf("value %v is not TOML-serializable", raw)
}

Type guard

func tomlSafeValue(v any) bool {
	switch v.(type) { case string, int64, float64, bool: return true }; return false
}

Try / catch

out, err := workspace.WriteUserConfigValue(data, key, wsKey, raw)
if err != nil && strings.Contains(err.Error(), "serialize user config") {
	// retry with a stringified scalar value
	out, err = workspace.WriteUserConfigValue(data, key, wsKey, fmt.Sprintf("%v", raw))
}

Prevention

When it happens

Trigger: WriteUserConfigValue called with a rawValue that parses (via parseValueString) into a TOML-incompatible value, then tree.ToTomlString() fails; also triggered by an entryKey or key path containing segments the TOML writer cannot render as table names.

Common situations: Passing JSON-like nested structures as raw values that don't round-trip through TOML; workspace keys containing characters that produce invalid TOML table headers; writing values via scripting with unquoted special characters.

Related errors


AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05). Data as JSON: /api/errors/538939704baba35c. Report an issue: GitHub.