{"record":{"id":"5c3483ad8f3ef93a","repo":"hasura/graphql-engine","slug":"platform-v-is-badly-constructed-w","errorCode":null,"errorMessage":"platform (%+v) is badly constructed: %w","messagePattern":"platform \\(%\\+v\\) is badly constructed: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/plugins/types.go","lineNumber":155,"sourceCode":"\t\treturn errors.E(op, \"should have a short description\")\n\t}\n\n\tif strings.ContainsAny(p.ShortDescription, \"\\r\\n\") {\n\t\treturn errors.E(op, \"should not have line breaks in short description\")\n\t}\n\n\tif len(p.Platforms) == 0 {\n\t\treturn errors.E(op, \"should have a platform specified\")\n\t}\n\n\tif p.Version == \"\" {\n\t\treturn errors.E(op, \"should have a version specified\")\n\t}\n\n\tfor _, pl := range p.Platforms {\n\t\terr := validatePlatform(pl)\n\t\tif err != nil {\n\t\t\treturn errors.E(op, fmt.Errorf(\"platform (%+v) is badly constructed: %w\", pl, err))\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// Platform describes how to perform an installation on a specific platform\n// and how to match the target platform (os, arch).\ntype Platform struct {\n\tURI      string          `json:\"uri,omitempty\"`\n\tSha256   string          `json:\"sha256,omitempty\"`\n\tFiles    []FileOperation `json:\"files\"`\n\tSelector string          `json:\"selector\"`\n\t// Bin specifies the path to the plugin executable.\n\t// The path is relative to the root of the installation folder.\n\t// The binary will be linked after all FileOperations are executed.\n\tBin string `json:\"bin\"`\n}","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/hasura/graphql-engine/blob/724551b9ae87845594ef0408cff0e50eb6c90dc5/cli/plugins/types.go#L137-L173","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the wrapped error text after the colon — it names the exact missing field (e.g. \"`bin` has to be set\").","Match the failing entry against the %+v dump printed in the message to find its index in p.Platforms.","Fill in all required platform fields: os, arch, url, sha256 (hex, matching sha256Pattern), bin, and valid files operations."],"exampleFix":"// before\n\"platforms\": [{ \"os\": \"linux\", \"arch\": \"amd64\", \"url\": \"https://...\", \"bin\": \"\" }]\n\n// after\n\"platforms\": [{ \"os\": \"linux\", \"arch\": \"amd64\", \"url\": \"https://...\", \"sha256\": \"<64 hex chars>\", \"bin\": \"myplugin\" }]","handlingStrategy":"validation","validationCode":"for i, pl := range p.Platforms {\n\tif err := validatePlatform(pl); err != nil { // or your own equivalent checks\n\t\treturn fmt.Errorf(\"platform[%d] (%s/%s): %w\", i, pl.Os, pl.Arch, err)\n\t}\n}","typeGuard":null,"tryCatchPattern":"if err := p.ValidatePlugin(name); err != nil {\n\tif strings.Contains(err.Error(), \"badly constructed\") {\n\t\t// the wrapped message names the missing field; fix that platform entry\n\t}\n}","preventionTips":["Fill every required platform field: os, arch, url, sha256, bin, files.","Validate manifests in CI before release using ReadPluginFromFile.","Use a JSON schema for plugin manifests so editors catch missing fields early."],"tags":["plugins","validation","manifest","platforms"],"backgroundTag":"manifest-field-mismatch","analyzedSha":"724551b9ae87845594ef0408cff0e50eb6c90dc5","analyzedAt":"2026-08-28T07:32:55.105Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}