dagger/dagger · error

unmarshal module config: %w

Error message

unmarshal module config: %w

What it means

ModuleConfig.UnmarshalJSON decodes into an alias of ModuleConfig plus an extra Runtime *SDK field, because current configs may spell the sdk key as "runtime". If the underlying json.Unmarshal of the whole config fails — any field anywhere in the config has a wrong JSON type or the JSON is malformed — it is wrapped as "unmarshal module config" so the config-level decode failure is clearly attributed.

Source

Thrown at core/modules/config.go:282

	*sdk = SDK(tmp)
	return nil
}

func (modCfg *ModuleConfig) UnmarshalJSON(data []byte) error {
	if modCfg == nil {
		return fmt.Errorf("cannot unmarshal into nil %T", modCfg)
	}
	if len(data) == 0 {
		return nil
	}

	type alias ModuleConfig // lets us use the default json unmashaler
	var tmp struct {
		alias
		Runtime *SDK `json:"runtime,omitempty"`
	}
	if err := json.Unmarshal(data, &tmp); err != nil {
		return fmt.Errorf("unmarshal module config: %w", err)
	}
	if tmp.Runtime != nil {
		if tmp.SDK != nil && !reflect.DeepEqual(tmp.SDK, tmp.Runtime) {
			return fmt.Errorf("module config cannot set both sdk and runtime")
		}
		tmp.SDK = tmp.Runtime
	}

	loaded := ModuleConfig(tmp.alias)
	normalizeLoadedModuleConfig(&loaded)
	*modCfg = loaded
	return nil
}

func normalizeLoadedModuleConfig(modCfg *ModuleConfig) {
	if modCfg == nil {
		return
	}

View on GitHub (pinned to 82ba2681db)

Solutions

  1. Run `jq . dagger.json` (or a JSON linter) to locate the malformed portion of the config
  2. Compare the failing field's type against the ModuleConfig schema in core/modules/config.go and fix the JSON type (arrays, objects, strings)
  3. Regenerate the config with a matching dagger CLI version (`dagger mod sync`) to normalize the schema
  4. If the file was written by an older dagger version, load it once with that version and let the CLI migrate it

Example fix

// dagger.json before
"include": "*.go"        // should be an array
// after
"include": ["*.go"]
Defensive patterns

Strategy: validation

Validate before calling

// spot-check core field types before loading
var probe struct {
	Include      []string          `json:"include"`
	Exclude      []string          `json:"exclude"`
	Dependencies []json.RawMessage `json:"dependencies"`
	SDK          json.RawMessage   `json:"sdk"`
	Runtime      json.RawMessage   `json:"runtime"`
}
if err := json.Unmarshal(raw, &probe); err != nil {
	return fmt.Errorf("fix field types in dagger.json: %w", err)
}

Try / catch

var cfg modules.ModuleConfig
if err := json.Unmarshal(raw, &cfg); err != nil {
	return fmt.Errorf("invalid dagger.json: %w", err)
}

Prevention

When it happens

Trigger: Loading a dagger.json where any ModuleConfig field has a mismatched JSON type (e.g. include/exclude as a string instead of an array, dependencies as an object instead of a list) or the file is otherwise invalid JSON; decoding via UnmarshalModuleConfig or the ModuleConfigWithUserFields unmarshaler which delegates here.

Common situations: Hand-edited configs with wrong types; config generated by an older or newer dagger version whose schema drifted; truncated or corrupted dagger.json files.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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