{"record":{"id":"73101c5047b92e50","repo":"larksuite/cli","slug":"suite-route-for-s-is-missing-or-duplicated","errorCode":null,"errorMessage":"suite route for %s is missing or duplicated","messagePattern":"suite route for (.+?) is missing or duplicated","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/skillscheck/layout.go","lineNumber":134,"sourceCode":"\t\treturn fmt.Errorf(\"write cropped suite SKILL.md: %w\", err)\n\t}\n\n\tkept, err := listDirectSubdirs(referencesPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"verify cropped suite: %w\", err)\n\t}\n\treturn assertSameSkillNames(kept, target, \"cropped suite\")\n}\n\nfunc cropSuiteRoutes(content string, removed, target []string) (string, error) {\n\trouteLine := func(name string) *regexp.Regexp {\n\t\treturn regexp.MustCompile(`(?m)^- ` + regexp.QuoteMeta(name) + `(?:（[^）\\n]*）)?:[^\\n]*(?:\\n|$)`)\n\t}\n\n\tfor _, name := range removed {\n\t\tline := routeLine(name)\n\t\tif len(line.FindAllStringIndex(content, -1)) != 1 {\n\t\t\treturn \"\", fmt.Errorf(\"suite route for %s is missing or duplicated\", name)\n\t\t}\n\t\tcontent = line.ReplaceAllString(content, \"\")\n\t}\n\n\tfor _, name := range target {\n\t\tif len(routeLine(name).FindAllStringIndex(content, -1)) != 1 {\n\t\t\treturn \"\", fmt.Errorf(\"cropped suite route for %s is missing or duplicated\", name)\n\t\t}\n\t}\n\n\tkeywords := suiteKeywords(content)\n\tstart := strings.Index(content, suiteDescriptionPrefix)\n\tif start < 0 {\n\t\treturn \"\", fmt.Errorf(\"suite description prefix is missing\")\n\t}\n\tvalueStart := start + len(suiteDescriptionPrefix)\n\tvalueEndOffset := strings.Index(content[valueStart:], suiteDescriptionSuffix)\n\tif valueEndOffset < 0 {","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/skillscheck/layout.go#L116-L152","documentation":"cropSuiteRoutes expects exactly one route bullet in SKILL.md for a removed skill (matched by the per-name regex); it found zero or more than one, so safe cropping is impossible - the archive's route format deviates from the generator's contract.","triggerScenarios":"Thrown at internal/skillscheck/layout.go:134 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Align the suite SKILL.md route list with the reference directories (exactly one bullet per skill)"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"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"}