hashicorp/nomad · error

failed to decode object: %v

Error message

failed to decode object: %v

What it means

Once the root is confirmed an ObjectList, the first item is decoded into a map via hcl.DecodeObject. Failure here (types not decodable, unsupported constructs) is wrapped as this error, before the function returns m["config"].

Source

Thrown at plugins/shared/cmd/launcher/command/device.go:238

	if len(config) == 0 {
		return map[string]any{}, nil
	}

	// Parse as we do in the jobspec parser
	root, err := hcl.Parse(string(config))
	if err != nil {
		return nil, fmt.Errorf("failed to hcl parse the config: %v", err)
	}

	// Top-level item should be a list
	list, ok := root.Node.(*ast.ObjectList)
	if !ok {
		return nil, fmt.Errorf("root should be an object")
	}

	var m map[string]any
	if err := hcl.DecodeObject(&m, list.Items[0]); err != nil {
		return nil, fmt.Errorf("failed to decode object: %v", err)
	}

	return m["config"], nil
}

func (c *Device) startRepl() error {
	// Start the output goroutine
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	fingerprint := make(chan context.Context)
	stats := make(chan context.Context)
	reserve := make(chan []string)
	go c.replOutput(ctx, fingerprint, stats, reserve)

	c.Ui.Output("> Availabile commands are: exit(), fingerprint(), stop_fingerprint(), stats(), stop_stats(), reserve(id1, id2, ...)")
	var fingerprintCtx, statsCtx context.Context
	var fingerprintCancel, statsCancel context.CancelFunc

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Simplify the top-level config block so its body decodes into a plain map (key = value assignments).
  2. Move complex/nested structures under the `config` key with supported syntax.
  3. Check the wrapped %v error for the offending key/line and fix its type.
  4. Test the config through the device plugin's schema (hclspec) path if supported, which validates types earlier.

Example fix

// before
config "mock" {
  options = [ { a = 1 } ]
}
// after
config "mock" {
  options = ["a=1"]
}
Defensive patterns

Strategy: validation

Validate before calling

// Prefer validating config against the device schema (hclspec) before legacy decode
schema, err := c.getSpec()
if err != nil {
	return err
}
if _, diag := hclspecutils.Convert(schema); diag.HasErrors() {
	return fmt.Errorf("device schema invalid: %v", diag)
}

Try / catch

if err := setConfigErr; err != nil && strings.Contains(err.Error(), "failed to decode object") {
	// log the wrapped decoder error and fall back to schema-based parsing if available
}

Prevention

When it happens

Trigger: hcl.DecodeObject fails on the top-level block item, e.g. keys with incompatible value types, nested structures the legacy decoder cannot handle, or block items where assignments are expected.

Common situations: Config values with types the legacy hcl decoder mishandles (lists of objects, heredocs in odd positions); mixing blocks where a single object is expected; porting config from newer hcl2 syntax not supported by the legacy decoder.

Understand the failure class

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/ee3f8384983017a5. Report an issue: GitHub.