alibaba/nacos · error · NacosApiException

20004

20004

Error message

Base version not found: {basedOnVersion}

What it means

Thrown by PromptOperationServiceImpl.createDraft when forking (basedOnVersion supplied) but resourceManager.findVersion returns null for that version — the base version to fork from does not exist for this prompt. Reported as RESOURCE_NOT_FOUND (HTTP 404). Note: listing shows code=20004 which is the RESOURCE_NOT_FOUND numeric code.

Source

Thrown at ai/src/main/java/com/alibaba/nacos/ai/service/prompt/PromptOperationServiceImpl.java:180

            AiResourceTraceService.logSuccess(RESOURCE_TYPE_PROMPT, promptKey, version,
                AiResourceTraceService.OP_CREATE_DRAFT, VisibilityHelper.resolveCurrentIdentity(),
                VisibilityHelper.resolveClientIp());
            
            return version;
        }
        
        // Existing prompt
        VisibilityHelper.checkWritableResource(meta);
        PromptVersionInfoPojo info = requireVersionInfo(meta);
        ResourceVersionInfo resourceInfo = toResourceVersionInfo(info);
        AiResourceManager.ensureNoWorkingVersion(resourceInfo, "create draft");
        
        if (StringUtils.isNotBlank(basedOnVersion)) {
            // Fork from existing version
            AiResourceVersion baseRow = resourceManager.findVersion(namespaceId, promptKey,
                RESOURCE_TYPE_PROMPT, basedOnVersion);
            if (baseRow == null) {
                throw new NacosApiException(NacosException.NOT_FOUND, ErrorCode.RESOURCE_NOT_FOUND,
                    "Base version not found: " + basedOnVersion);
            }
            PromptVersionInfo baseContent = loadPromptFromStorage(namespaceId, promptKey,
                basedOnVersion, baseRow.getStorage());
            String newVersion = StringUtils.isBlank(targetVersion)
                ? incrementVersion(basedOnVersion) : targetVersion;
            validateVersion(newVersion);
            checkVersionNotExists(namespaceId, promptKey, newVersion);
            
            String storageJson = writePromptToStorage(namespaceId, promptKey, newVersion,
                baseContent.getTemplate(), baseContent.getVariables(), null);
            
            String currentUser = VisibilityHelper.resolveCurrentIdentity();
            resourceManager.insertVersionRow(namespaceId, promptKey, RESOURCE_TYPE_PROMPT,
                StringUtils.isBlank(currentUser) ? DEFAULT_AUTHOR : currentUser,
                VERSION_STATUS_DRAFT, newVersion, commitMsg, storageJson);
            
            resourceManager.markEditingVersionCas(namespaceId, meta, resourceInfo, newVersion,

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. List the prompt's versions and use an existing one as basedOnVersion.
  2. Verify the version string matches exactly (case, no whitespace).
  3. If the base was deleted, fork from the latest remaining published version.
  4. If you want a fresh draft from scratch, omit basedOnVersion and supply a template instead.

Example fix

// before
promptService.createDraft(ns, key, "9.9.9", null, ...); // base not found
// after
List<String> versions = listPromptVersions(ns, key);
String base = versions.isEmpty() ? null : versions.get(versions.size() - 1);
promptService.createDraft(ns, key, base, null, ...);
Defensive patterns

Strategy: validation

Validate before calling

// Confirm basedOnVersion exists before forking
if (basedOnVersion != null && !basedOnVersion.isBlank()) {
    List<String> versions = promptService.listVersions(ns, promptKey);
    if (!versions.contains(basedOnVersion)) {
        throw new IllegalArgumentException("Unknown base version: " + basedOnVersion);
    }
}
promptService.createDraft(ns, promptKey, basedOn, target, template, vars, msg, desc, tags);

Try / catch

try {
    promptService.createDraft(ns, key, basedOn, target, template, vars, msg, desc, tags);
} catch (NacosApiException e) {
    if (e.getErrCode() == ErrorCode.RESOURCE_NOT_FOUND.getCode()
        && e.getErrMsg().contains("Base version not found")) {
        // fork from the latest existing version instead
        basedOn = listVersions(ns, key).stream().reduce((a, b) -> b).orElse(null);
        promptService.createDraft(ns, key, basedOn, target, template, vars, msg, desc, tags);
    } else { throw e; }
}

Prevention

When it happens

Trigger: createDraft with a basedOnVersion that was never published, was deleted, or is mistyped for the given promptKey.

Common situations: Stale version reference after a rollback; cross-environment copy where the source version is absent; typo in basedOnVersion; race where the version was deleted between a list and the fork.

Related errors


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