{"record":{"id":"c0bde2d6949d166f","repo":"larksuite/cli","slug":"l1-outputschema-must-not-be-nil","errorCode":null,"errorMessage":"L1: outputSchema must not be nil","messagePattern":"L1: outputSchema must not be nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/schema/lint.go","lineNumber":47,"sourceCode":"func 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\n\t// L1: validate every Property type recursively\n\tif env.InputSchema != nil && env.InputSchema.Properties != nil {\n\t\tvalidatePropertyTypes(env.InputSchema.Properties, &errs)\n\t}","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/schema/lint.go#L29-L65","documentation":"lintEnvelope validates both directions of an envelope's schema contract; this L1 error indicates the OutputSchema field is nil. Every envelope must declare an object-typed output schema describing its result shape, so a missing output schema fails the structural lint.","triggerScenarios":"Registering or linting an Envelope with OutputSchema unset (nil), typically when the author assumed output shape need not be declared.","commonSituations":"New envelopes authored quickly without result documentation; refactors that split schema definitions and drop the output half; test fixtures built with only InputSchema populated.","solutions":["Set OutputSchema to a non-nil Schema with Type \"object\" describing the envelope's result fields.","Mirror the input-schema pattern used by neighboring envelopes in the same registry.","Run the envelope lint suite to verify all envelopes in the registry now pass L1."],"exampleFix":"// before\nenv := Envelope{Name: \"send.message\", InputSchema: in}\n// after\nenv := Envelope{Name: \"send.message\", InputSchema: in, OutputSchema: &Schema{Type: \"object\", Properties: resultProps}}","handlingStrategy":"validation","validationCode":"func validateOutputSchema(env *Envelope) error {\n    if env.OutputSchema == nil {\n        return errors.New(\"envelope must declare a non-nil OutputSchema\")\n    }\n    return nil\n}","typeGuard":"if env.OutputSchema == nil {\n    // handle: output schema missing\n}","tryCatchPattern":"if err := lintEnvelope(env); err != nil {\n    // look for \"outputSchema must not be nil\" and add the schema\n}","preventionTips":["Define input and output schemas side by side in the same struct literal.","Keep a registry test that lints every envelope on every build.","Copy full envelope templates, not partial ones."],"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"}