{"record":{"id":"9ea5f3becbe13023","repo":"larksuite/cli","slug":"input-relations-d-duplicates-an-earlier-relation","errorCode":null,"errorMessage":"Input.Relations[%d] duplicates an earlier relation","messagePattern":"Input\\.Relations\\[(.+?)\\] duplicates an earlier relation","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/common/typed_compile_contract.go","lineNumber":51,"sourceCode":"\t\t\treturn nil, fmt.Errorf(\"Input.Relations[%d].Stage %q is invalid\", i, definition.Stage)\n\t\t}\n\t\tcompiled := compiledRelation{kind: definition.Kind, presence: definition.Presence, stage: definition.Stage}\n\t\tlocal := make(map[string]struct{})\n\t\tfor _, name := range definition.Params {\n\t\t\tfield, ok := fieldByName[name]\n\t\t\tif !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"Input.Relations[%d] references unknown param --%s\", i, name)\n\t\t\t}\n\t\t\tif _, duplicate := local[name]; duplicate {\n\t\t\t\treturn nil, fmt.Errorf(\"Input.Relations[%d] repeats param --%s\", i, name)\n\t\t\t}\n\t\t\tlocal[name] = struct{}{}\n\t\t\tcompiled.fields = append(compiled.fields, field)\n\t\t}\n\t\tkeyBytes, _ := json.Marshal(definition)\n\t\tkey := string(keyBytes)\n\t\tif _, duplicate := seen[key]; duplicate {\n\t\t\treturn nil, fmt.Errorf(\"Input.Relations[%d] duplicates an earlier relation\", i)\n\t\t}\n\t\tseen[key] = struct{}{}\n\t\tresult = append(result, compiled)\n\t}\n\treturn result, nil\n}\n\nfunc compileAuthorization(definition typedAuthorizationDefinition, fields []compiledInputField, fieldByName map[string]int) error {\n\tfor identity, authorization := range definition.Identities {\n\t\tfor i, conditional := range authorization.ConditionalScopes {\n\t\t\tpath := fmt.Sprintf(\"Authorization.%s.ConditionalScopes[%d]\", identity, i)\n\t\t\tif len(conditional.Params) > 0 && conditional.When == \"\" {\n\t\t\t\treturn fmt.Errorf(\"%s.Params requires agent-readable When text\", path)\n\t\t\t}\n\t\t\tseen := make(map[string]struct{}, len(conditional.Params))\n\t\t\tfor j, param := range conditional.Params {\n\t\t\t\tif param == \"\" || param != strings.TrimSpace(param) {\n\t\t\t\t\treturn fmt.Errorf(\"%s.Params[%d] must be a non-blank trimmed param\", path, j)","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/common/typed_compile_contract.go#L33-L69","documentation":"Thrown when two relations in Input.Relations are structurally identical — the compiler JSON-marshals each definition and rejects a relation whose key was already seen. Duplicate relations add no information and would compile to ambiguous behavior.","triggerScenarios":"Input.Relations contains two Relation entries with identical Kind, Presence, Stage, and Params, e.g. from an accidental copy-paste.","commonSituations":"Copy-pasting a relation block and forgetting to edit it; merging definitions from two shortcuts; programmatic generation appending the same relation twice.","solutions":["Delete the redundant relation entry","Differentiate the relations (distinct Kind/Presence/Stage/Params) if both were intentional"],"exampleFix":"// before\nRelations: []Relation{\n  {Kind: \"lookup\", Params: []string{\"--chat-id\"}},\n  {Kind: \"lookup\", Params: []string{\"--chat-id\"}},\n}\n// after\nRelations: []Relation{\n  {Kind: \"lookup\", Params: []string{\"--chat-id\"}},\n}","handlingStrategy":"validation","validationCode":"keys := map[string]struct{}{}\nfor _, rel := range def.Input.Relations {\n  b, _ := json.Marshal(rel)\n  if _, dup := keys[string(b)]; dup { return fmt.Errorf(\"duplicate relation\") }\n  keys[string(b)] = struct{}{}\n}","typeGuard":null,"tryCatchPattern":"if err := common.CompileTypedDefinition(def); err != nil {\n  return fmt.Errorf(\"duplicate relation: %w\", err)\n}","preventionTips":["Copy-paste relation blocks only with an immediate edit of Kind or Params","Generate relations from a map to avoid accidental repetition","Add a compile-all-definitions test"],"tags":["go","shortcut-definition","validation","duplicate"],"backgroundTag":"shortcut-definition-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"}