{"record":{"id":"e64d20e692a51ff3","repo":"multica-ai/multica","slug":"either-url-or-file-is-required","errorCode":null,"errorMessage":"either --url or --file is required","messagePattern":"either --url or --file is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/cmd/multica/cmd_skill.go","lineNumber":460,"sourceCode":"\tif output == \"json\" {\n\t\treturn cli.PrintJSON(os.Stdout, result)\n\t}\n\n\tfmt.Printf(\"Skill updated from source: %s (%s)\\n\", strVal(result, \"name\"), strVal(result, \"id\"))\n\treturn nil\n}\n\nfunc runSkillImport(cmd *cobra.Command, _ []string) error {\n\tclient, err := newAPIClient(cmd)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\timportURL, _ := cmd.Flags().GetString(\"url\")\n\timportFile, _ := cmd.Flags().GetString(\"file\")\n\tswitch {\n\tcase importURL == \"\" && importFile == \"\":\n\t\treturn fmt.Errorf(\"either --url or --file is required\")\n\tcase importURL != \"\" && importFile != \"\":\n\t\treturn fmt.Errorf(\"--url and --file are mutually exclusive\")\n\t}\n\tonConflict, _ := cmd.Flags().GetString(\"on-conflict\")\n\tif !validSkillImportConflictStrategy(onConflict) {\n\t\treturn fmt.Errorf(\"--on-conflict must be one of: fail, overwrite, rename, skip\")\n\t}\n\n\tctx, cancel := context.WithTimeout(context.Background(), cli.AtLeastAPITimeout(60*time.Second))\n\tdefer cancel()\n\n\tvar result map[string]any\n\tif importFile != \"\" {\n\t\tfileData, readErr := os.ReadFile(importFile)\n\t\tif readErr != nil {\n\t\t\treturn fmt.Errorf(\"read skill archive: %w\", readErr)\n\t\t}\n\t\tif err := client.ImportSkillFile(ctx, fileData, filepath.Base(importFile), onConflict, &result); err != nil {","sourceCodeStart":442,"sourceCodeEnd":478,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/cmd/multica/cmd_skill.go#L442-L478","documentation":"Pure client-side flag validation in `multica skill import`: the command requires exactly one source for the skill bundle, and neither `--url` nor `--file` was provided. No network call has been made yet — cobra returns this before the API client is even used for the request.","triggerScenarios":"Running `multica skill import` with no flags; providing only auxiliary flags like `--on-conflict skip` while forgetting the source; a wrapper script that builds the command from variables where both the URL and file variables are empty strings.","commonSituations":"Shell script passes \"$SKILL_URL\" but the env var is unset, expanding to nothing; user assumes the command is interactive and prompts for a source; CI job parameter misconfiguration.","solutions":["Add exactly one source flag: `multica skill import --url https://example.com/skill.zip` or `multica skill import --file ./skill.zip`.","If driven by a script, default the variable or fail early: `: \"${SKILL_URL:?SKILL_URL must be set}\" before invoking the CLI.","Run `multica skill import --help` to review accepted flags."],"exampleFix":"# before\nmultica skill import\n\n# after\nmultica skill import --url https://example.com/skills/my-skill.zip --on-conflict fail","handlingStrategy":"validation","validationCode":": \"${SKILL_SRC:?set SKILL_SRC to a URL or local file path}\"\ncase \"$SKILL_SRC\" in\n  http://*|https://*) SRC_FLAG=(--url \"$SKILL_SRC\") ;;\n  *) test -f \"$SKILL_SRC\" || { echo \"not a file: $SKILL_SRC\"; exit 1; }; SRC_FLAG=(--file \"$SKILL_SRC\") ;;\nesac\nmultica skill import \"${SRC_FLAG[@]}\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Model the import source as one variable and derive the flag from it, so 'neither flag' cannot happen.","Fail fast on empty variables (: ${VAR:?}) before invoking the CLI.","Read `multica skill import --help` once when adding the command to a script."],"tags":["cli","validation","flags","skill","import"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}