{"record":{"id":"893ea8feebde175c","repo":"larksuite/cli","slug":"l1-inputschema-properties-must-not-be-nil","errorCode":null,"errorMessage":"L1: inputSchema.properties must not be nil","messagePattern":"L1: inputSchema\\.properties must not be nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/schema/lint.go","lineNumber":43,"sourceCode":"}\n\n// lintEnvelope runs L1-L3 checks and returns a list of errors. Empty slice\n// means the envelope is compliant.\nfunc lintEnvelope(env Envelope) []error {\n\tvar errs []error\n\n\t// ---- L1: structural ----\n\tif env.Name == \"\" {\n\t\terrs = append(errs, errors.New(\"L1: name must not be empty\"))\n\t}\n\tif env.InputSchema == nil {\n\t\terrs = append(errs, errors.New(\"L1: inputSchema must not be nil\"))\n\t} else {\n\t\tif env.InputSchema.Type != \"object\" {\n\t\t\terrs = append(errs, fmt.Errorf(\"L1: inputSchema.type = %q, want \\\"object\\\"\", env.InputSchema.Type))\n\t\t}\n\t\tif env.InputSchema.Properties == nil {\n\t\t\terrs = append(errs, errors.New(\"L1: inputSchema.properties must not be nil\"))\n\t\t}\n\t}\n\tif env.OutputSchema == nil {\n\t\terrs = append(errs, errors.New(\"L1: outputSchema must not be nil\"))\n\t} else {\n\t\tif env.OutputSchema.Type != \"object\" {\n\t\t\terrs = append(errs, fmt.Errorf(\"L1: outputSchema.type = %q, want \\\"object\\\"\", env.OutputSchema.Type))\n\t\t}\n\t}\n\tif env.Meta == nil {\n\t\terrs = append(errs, errors.New(\"L1: _meta must not be nil\"))\n\t\t// Cannot continue meta-dependent checks\n\t\treturn errs\n\t}\n\tif env.Meta.EnvelopeVersion != \"1.0\" {\n\t\terrs = append(errs, fmt.Errorf(\"L1: _meta.envelope_version = %q, want \\\"1.0\\\"\", env.Meta.EnvelopeVersion))\n\t}\n","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/schema/lint.go#L25-L61","documentation":"This L1 structural lint error fires when an envelope declares an InputSchema but leaves its Properties map nil. The lint contract requires every object-type input schema to enumerate its properties explicitly, so a nil map is treated as an incomplete schema rather than 'no properties'.","triggerScenarios":"Linting an envelope whose InputSchema is non-nil with Type \"object\" but Properties == nil, e.g. &Schema{Type: \"object\"} without a properties map.","commonSituations":"Copy-pasting minimal schema structs from docs; constructing schemas programmatically and forgetting to initialize the map; JSON round-trips where \"properties\" was omitted and decoded into a nil map.","solutions":["Initialize InputSchema.Properties to a non-nil map, adding entries for each accepted parameter.","If the command truly takes no parameters, set Properties to an empty non-nil map: map[string]*Property{}.","Add a unit test constructing the envelope so TestAllEnvelopesPass-style lint coverage catches regressions."],"exampleFix":"// before\nInputSchema: &Schema{Type: \"object\"}\n// after\nInputSchema: &Schema{Type: \"object\", Properties: map[string]*Property{}}","handlingStrategy":"validation","validationCode":"func hasProperties(s *Schema) bool { return s != nil && s.Type == \"object\" && s.Properties != nil }","typeGuard":"if env.InputSchema != nil && env.InputSchema.Properties == nil {\n    // handle: properties map missing\n}","tryCatchPattern":"if err := lintEnvelope(env); err != nil {\n    // scan error strings for \"inputSchema.properties\" and fix the schema\n}","preventionTips":["Use a constructor like newObjectSchema(props...) that always allocates the map.","Never decode schemas without re-initializing Properties when absent.","Lint envelopes in unit tests before registering them."],"tags":["go","schema","validation","envelope"],"backgroundTag":"schema-validation-failed","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"}