{"record":{"id":"caecc0335d0c4855","repo":"alibaba/nacos","slug":"parameter-validate-error-caecc0","errorCode":"PARAMETER_VALIDATE_ERROR","errorMessage":"skillCard name must match skillName parameter","messagePattern":"skillCard name must match skillName parameter","errorType":"exception","errorClass":"NacosApiException","httpStatus":400,"severity":"warning","filePath":"ai/src/main/java/com/alibaba/nacos/ai/form/skills/admin/SkillDraftCreateForm.java","lineNumber":125,"sourceCode":"    public void setTargetVersion(String targetVersion) {\n        this.targetVersion = targetVersion;\n    }\n    \n    public String getCommitMsg() {\n        return commitMsg;\n    }\n    \n    public void setCommitMsg(String commitMsg) {\n        this.commitMsg = commitMsg;\n    }\n    \n    private Skill parseInitialSkillOrNull() throws NacosApiException {\n        if (StringUtils.isBlank(getSkillCard())) {\n            return null;\n        }\n        Skill skill = SkillRequestUtil.parseSkill(this);\n        if (StringUtils.isNotBlank(getSkillName()) && !getSkillName().equals(skill.getName())) {\n            throw new NacosApiException(NacosException.INVALID_PARAM,\n                ErrorCode.PARAMETER_VALIDATE_ERROR,\n                \"skillCard name must match skillName parameter\");\n        }\n        return skill;\n    }\n    \n    private String requireResolvedSkillName(Skill initialOrNull) throws NacosApiException {\n        String skillName = StringUtils.isNotBlank(getSkillName()) ? getSkillName()\n            : (initialOrNull != null ? initialOrNull.getName() : null);\n        if (StringUtils.isBlank(skillName)) {\n            throw new NacosApiException(NacosException.INVALID_PARAM, ErrorCode.PARAMETER_MISSING,\n                \"skillName or skillCard with name is required\");\n        }\n        return skillName;\n    }\n}\n","sourceCodeStart":107,"sourceCodeEnd":142,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/ai/src/main/java/com/alibaba/nacos/ai/form/skills/admin/SkillDraftCreateForm.java#L107-L142","documentation":"SkillDraftCreateForm.parseInitialSkillOrNull() (called by prepareCreateDraftRequest) parses the skillCard JSON and, if the request also carries a top-level `skillName`, requires that the two names be exactly equal. Mismatched names are rejected with PARAMETER_VALIDATE_ERROR to prevent ambiguity about which skill a draft belongs to. The comparison is exact (case-sensitive) using String.equals.","triggerScenarios":"Sending create-draft with BOTH a `skillName` parameter AND a `skillCard` whose inner `name` field differs — e.g. skillName=\"my-skill\" but skillCard.name=\"my-skill-v2\". Only triggered when both are present and non-blank.","commonSituations":"Frontend pre-filling skillName from an old value while the user edited the name inside the card editor; copy-pasting a skillCard from another skill without updating the top-level skillName; case differences (\"MySkill\" vs \"myskill\") since the check is case-sensitive.","solutions":["Make skillName and skillCard.name exactly identical (same case) before sending.","Omit the top-level skillName entirely and let the server read the name from the card.","Re-derive skillName from the edited card object right before serialization."],"exampleFix":"// before\n{\"skillName\":\"my-skill\",\"skillCard\":\"{\\\"name\\\":\\\"my-skill-v2\\\",...}\"}\n// after\n{\"skillName\":\"my-skill-v2\",\"skillCard\":\"{\\\"name\\\":\\\"my-skill-v2\\\",...}\"}","handlingStrategy":"validation","validationCode":"// Ensure skillName and card name agree before sending\nSkill parsed = SkillRequestUtil.parseSkill(form);\nif (form.getSkillName() != null && !form.getSkillName().isBlank()\n    && !form.getSkillName().equals(parsed.getName())) {\n    throw new IllegalArgumentException(\"skillName must equal skillCard.name\");\n}","typeGuard":"// TypeScript\nconst namesAgree = (skillName: string, card: string): boolean => {\n  try { return JSON.parse(card).name === skillName; } catch { return false; }\n};","tryCatchPattern":"try {\n    form.prepareCreateDraftRequest(); // runs parseInitialSkillOrNull\n} catch (NacosApiException e) {\n    // names mismatch — sync skillName from the card editor\n}","preventionTips":["Derive the top-level skillName from the card object right before serialize; don't keep two editable copies.","Omit top-level skillName and let the server read it from the card.","Watch for case differences — the check is case-sensitive."],"tags":["validation","skill-api","draft","consistency","parameter-validation"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}