hasura/graphql-engine · error

platform (%+v) is badly constructed: %w

Error message

platform (%+v) is badly constructed: %w

What it means

ValidatePlugin iterates p.Platforms and each entry must pass validatePlatform. This error wraps the underlying platform validation failure (missing/invalid os, arch, url, bin, sha256, or files) together with a dump of the offending platform struct, so you can identify which entry in the platforms array is malformed.

Source

Thrown at cli/plugins/types.go:155

		return errors.E(op, "should have a short description")
	}

	if strings.ContainsAny(p.ShortDescription, "\r\n") {
		return errors.E(op, "should not have line breaks in short description")
	}

	if len(p.Platforms) == 0 {
		return errors.E(op, "should have a platform specified")
	}

	if p.Version == "" {
		return errors.E(op, "should have a version specified")
	}

	for _, pl := range p.Platforms {
		err := validatePlatform(pl)
		if err != nil {
			return errors.E(op, fmt.Errorf("platform (%+v) is badly constructed: %w", pl, err))
		}
	}

	return nil
}

// Platform describes how to perform an installation on a specific platform
// and how to match the target platform (os, arch).
type Platform struct {
	URI      string          `json:"uri,omitempty"`
	Sha256   string          `json:"sha256,omitempty"`
	Files    []FileOperation `json:"files"`
	Selector string          `json:"selector"`
	// Bin specifies the path to the plugin executable.
	// The path is relative to the root of the installation folder.
	// The binary will be linked after all FileOperations are executed.
	Bin string `json:"bin"`
}

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Read the wrapped error text after the colon — it names the exact missing field (e.g. "`bin` has to be set").
  2. Match the failing entry against the %+v dump printed in the message to find its index in p.Platforms.
  3. Fill in all required platform fields: os, arch, url, sha256 (hex, matching sha256Pattern), bin, and valid files operations.

Example fix

// before
"platforms": [{ "os": "linux", "arch": "amd64", "url": "https://...", "bin": "" }]

// after
"platforms": [{ "os": "linux", "arch": "amd64", "url": "https://...", "sha256": "<64 hex chars>", "bin": "myplugin" }]
Defensive patterns

Strategy: validation

Validate before calling

for i, pl := range p.Platforms {
	if err := validatePlatform(pl); err != nil { // or your own equivalent checks
		return fmt.Errorf("platform[%d] (%s/%s): %w", i, pl.Os, pl.Arch, err)
	}
}

Try / catch

if err := p.ValidatePlugin(name); err != nil {
	if strings.Contains(err.Error(), "badly constructed") {
		// the wrapped message names the missing field; fix that platform entry
	}
}

Prevention

When it happens

Trigger: A platforms[] entry in the plugin manifest missing required fields — e.g. no "os"/"arch", empty "url", missing "sha256", empty "bin", or an invalid files list — surfaced when ReadPluginFromFile → ValidatePlugin runs.

Common situations: Hand-written plugin manifests missing the sha256 sum; platform entries copied from another plugin with the wrong os/arch keys; entries where "bin" path doesn't match the archive layout.

Related errors


AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28). Data as JSON: /api/errors/5c3483ad8f3ef93a. Report an issue: GitHub.