alibaba/nacos · warning · NacosApiException

20002

20002

Error message

Invalid version from {source}: '{version}', expected x.y.z or vN

What it means

An INVALID_PARAM (HTTP 400, ErrorCode PARAMETER_VALIDATE_ERROR/20002) from validateUploadVersionFormat: the version resolved from a source (SKILL.md YAML front-matter, or _meta.json inside the ZIP) is not a supported format. Supported formats are full semantic version x.y.z (e.g. 1.0.0) or the legacy vN form (e.g. v3). Short forms like 1.0 are only accepted on the lenient/normalized path, not the strict validation path.

Source

Thrown at ai/src/main/java/com/alibaba/nacos/ai/service/skills/SkillOperationServiceImpl.java:690

        SkillResource metaResource = skill.getResource().get(resourceId);
        if (metaResource == null || StringUtils.isBlank(metaResource.getContent())) {
            return null;
        }
        try {
            @SuppressWarnings("unchecked")
            Map<String, Object> meta = JacksonUtils.toObj(metaResource.getContent(), Map.class);
            Object version = meta == null ? null : meta.get("version");
            return version == null ? null : StringUtils.trim(String.valueOf(version));
        } catch (Exception e) {
            LOGGER.warn("Failed to resolve version from skill _meta.json: {}", e.getMessage());
            return null;
        }
    }
    
    private static String validateUploadVersionFormat(String version, String source)
        throws NacosApiException {
        if (!VersionUtils.isSupportedVersionFormat(version)) {
            throw new NacosApiException(NacosException.INVALID_PARAM,
                ErrorCode.PARAMETER_VALIDATE_ERROR,
                "Invalid version from " + source + ": '" + version
                    + "', expected x.y.z or vN");
        }
        return version;
    }
    
    private static UploadVersionCandidate buildLenientUploadVersionCandidate(String version,
        String source) {
        String candidate = StringUtils.trim(version);
        if (VersionUtils.isSupportedVersionFormat(candidate)) {
            return new UploadVersionCandidate(candidate, source);
        }
        String normalizedVersion = normalizeShortSemverVersion(candidate);
        if (normalizedVersion != null) {
            return UploadVersionCandidate.normalized(normalizedVersion, source, candidate);
        }
        return UploadVersionCandidate.invalid(candidate, source);

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Set the version to a full x.y.z value (e.g. 1.0.0) or a vN value (e.g. v3) in SKILL.md front-matter and/or _meta.json.
  2. Remove the version field to let the server fall back to the default 0.0.1 / auto-increment.
  3. Re-zip and re-upload.

Example fix

// before — SKILL.md front-matter
---
name: weather-tool
version: 1.0
---

// after
---
name: weather-tool
version: 1.0.0
---
Defensive patterns

Strategy: validation

Validate before calling

// Validate the declared version format before uploading.
String v = resolveVersionFromFrontmatter(skillMd);
if (StringUtils.isNotBlank(v) && !VersionUtils.isSupportedVersionFormat(v)) {
    // ask the author to use x.y.z or vN (or remove the field for default 0.0.1)
}

Prevention

When it happens

Trigger: Uploading a skill whose front-matter / _meta.json declares a version like '1.0', 'latest', a date, or any non-x.y.z/non-vN string, when the strict version resolution path is taken.

Common situations: Author used a short semver (1.0 / 1) expecting it to be accepted; used a tag like 'latest' or 'stable'; non-numeric or date-based versioning.

Related errors


AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14). Data as JSON: /api/errors/d069a7fa640b490c. Report an issue: GitHub.