{"record":{"id":"dc5215b89aea8915","repo":"larksuite/cli","slug":"l2-field-q-has-format-binary-but-type-q-wan","errorCode":null,"errorMessage":"L2: field %q has format: binary but type = %q (want string)","messagePattern":"L2: field %q has format: binary but type = %q \\(want string\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/schema/lint.go","lineNumber":123,"sourceCode":"\t\t\terrs = append(errs, fmt.Errorf(\"L3: _meta.access_tokens contains invalid value %q (allowed: user, bot)\", t))\n\t\t}\n\t}\n\n\treturn errs\n}\n\n// walkForL2 recursively applies per-field L2 checks (format:binary on\n// non-string; minimum>=maximum) plus the sub-object required-exists invariant.\n// Required only matters on object-typed Properties (e.g. the params / data\n// wrappers); leaf scalars ignore it.\nfunc walkForL2(props *OrderedProps, errs *[]error) {\n\tif props == nil {\n\t\treturn\n\t}\n\tfor _, k := range props.Order {\n\t\tp := props.Map[k]\n\t\tif p.Format == \"binary\" && p.Type != \"string\" {\n\t\t\t*errs = append(*errs, fmt.Errorf(\"L2: field %q has format: binary but type = %q (want string)\", k, p.Type))\n\t\t}\n\t\tif p.Minimum != nil && p.Maximum != nil && *p.Minimum >= *p.Maximum {\n\t\t\t*errs = append(*errs, fmt.Errorf(\"L2: field %q minimum (%v) >= maximum (%v)\", k, *p.Minimum, *p.Maximum))\n\t\t}\n\t\tif n := len(p.EnumDescriptions); n > 0 && n != len(p.Enum) {\n\t\t\t*errs = append(*errs, fmt.Errorf(\"L2: field %q enumDescriptions length (%d) != enum length (%d)\", k, n, len(p.Enum)))\n\t\t}\n\t\tif len(p.Required) > 0 && p.Properties != nil {\n\t\t\tfor _, r := range p.Required {\n\t\t\t\tif _, ok := p.Properties.Map[r]; !ok {\n\t\t\t\t\t*errs = append(*errs, fmt.Errorf(\"L2: required key %q in %q not found in its properties\", r, k))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif p.Properties != nil {\n\t\t\twalkForL2(p.Properties, errs)\n\t\t}\n\t}","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/schema/lint.go#L105-L141","documentation":"walkForL2's recursive per-field check: a property declares format: binary (file upload) but its JSON type is not string - binary payloads are transported as strings, so the combination is contradictory.","triggerScenarios":"walkForL2 visits a properties map where a property p has p.Format == \"binary\" and p.Type is something else (e.g. \"object\", \"integer\", or a typo).","commonSituations":"Hand-authoring a file-upload parameter and setting type to \"file\" or \"object\" instead of \"string\"; generator bug emitting wrong type for binary fields.","solutions":["Set the property's Type to \"string\" while keeping Format: \"binary\"","Remove the format:\"binary\" if the field is not actually binary","Fix the code/metadata generator that emitted the wrong type"],"exampleFix":"// before\nProperty{Type: \"object\", Format: \"binary\"}\n// after\nProperty{Type: \"string\", Format: \"binary\"}","handlingStrategy":"validation","validationCode":"for _, p := range props {\n  if p.Format == \"binary\" && p.Type != \"string\" {\n    return fmt.Errorf(\"binary field %s must have type string\", name)\n  }\n}","typeGuard":"func isBinaryString(p *Property) bool { return p.Format == \"binary\" && p.Type == \"string\" }","tryCatchPattern":null,"preventionTips":["Remember binary fields are base64 strings in JSON Schema: type string + format binary","Never set format:\"binary\" on non-string types","Check schema output with the `schema` command after metadata edits"],"tags":["json-schema","lint","binary"],"backgroundTag":"json-schema-type-mismatch","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}