{"record":{"id":"f77f763c3f515ed9","repo":"multica-ai/multica","slug":"repository-url-cannot-be-empty","errorCode":null,"errorMessage":"repository URL cannot be empty","messagePattern":"repository URL cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/cmd/multica/cmd_repo.go","lineNumber":111,"sourceCode":"\tUpdated     []workspaceRepo `json:\"updated,omitempty\"`\n\tRemoved     []workspaceRepo `json:\"removed,omitempty\"`\n\tRepos       []workspaceRepo `json:\"repos\"`\n}\n\nfunc repoURLsFromArgsAndFlags(cmd *cobra.Command, args []string) ([]string, error) {\n\tflagURLs, _ := cmd.Flags().GetStringArray(\"url\")\n\traw := append([]string{}, flagURLs...)\n\traw = append(raw, args...)\n\tif len(raw) == 0 {\n\t\treturn nil, fmt.Errorf(\"at least one repository URL is required\")\n\t}\n\n\turls := make([]string, 0, len(raw))\n\tseen := make(map[string]struct{}, len(raw))\n\tfor _, u := range raw {\n\t\tu = strings.TrimSpace(u)\n\t\tif u == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"repository URL cannot be empty\")\n\t\t}\n\t\tif _, ok := seen[u]; ok {\n\t\t\tcontinue\n\t\t}\n\t\tseen[u] = struct{}{}\n\t\turls = append(urls, u)\n\t}\n\treturn urls, nil\n}\n\nfunc fetchRepoWorkspace(ctx context.Context, client *cli.APIClient, workspaceID string) (repoWorkspaceResponse, error) {\n\tvar ws repoWorkspaceResponse\n\tif err := client.GetJSON(ctx, \"/api/workspaces/\"+workspaceID, &ws); err != nil {\n\t\treturn repoWorkspaceResponse{}, fmt.Errorf(\"get workspace: %w\", err)\n\t}\n\tif ws.Repos == nil {\n\t\tws.Repos = []workspaceRepo{}\n\t}","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/cmd/multica/cmd_repo.go#L93-L129","documentation":"Returned by `repoURLsFromArgsAndFlags` when a supplied repository URL trims to an empty string (`strings.TrimSpace(u) == \"\"`). Unlike the 'at least one' check, this fires when a URL slot exists but its content is blank — including whitespace-only values.","triggerScenarios":"Passing `--url \"\"`, `--url \"   \"`, or an empty positional arg (common with quoted empty shell variables or trailing spaces in generated lists).","commonSituations":"Scripts looping over a repo array that contains an empty element (`for r in \"${REPOS[@]}\"` with an empty entry); copy-paste leaving a stray `''` argument; whitespace artifacts from file reads.","solutions":["Remove empty/whitespace entries from the arguments or `--url` flags.","Filter the list in the calling script: `URLS=$(grep -v '^[[:space:]]*$' repos.txt`).","Validate each URL is non-empty and starts with the expected scheme (https://) before invoking the CLI."],"exampleFix":"# before\nREPOS=(\"\" \"https://github.com/acme/api\")\nfor r in \"${REPOS[@]}\"; do multica repo add \"$r\"; done\n# error: repository URL cannot be empty\n\n# after\nfor r in \"${REPOS[@]}\"; do [ -z \"$(printf '%s' \"$r\" | tr -d '[:space:]')\" ] && continue; multica repo add \"$r\"; done","handlingStrategy":"validation","validationCode":"# bash: strip empty/whitespace entries before invoking\nmapfile -t REPOS < <(grep -v '^[[:space:]]*$' repos.txt)\nmultica repo add \"${REPOS[@]}\"","typeGuard":"func isNonEmptyURL(u string) bool { return strings.TrimSpace(u) != \"\" }","tryCatchPattern":null,"preventionTips":["Trim whitespace and drop empty elements from URL arrays before passing them.","A quoted empty variable (`\"$EMPTY\"`) still produces an empty argument — check before quoting."],"tags":["go","cli","validation","repo","input-hygiene"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}