{"record":{"id":"ada49195328349f7","repo":"alibaba/nacos","slug":"ai-resource-version-row-is-invalid-name","errorCode":null,"errorMessage":"AI resource Version row is invalid: {name}","messagePattern":"AI resource Version row is invalid: (.+?)","errorType":"exception","errorClass":"NacosException","httpStatus":500,"severity":"critical","filePath":"ai/src/main/java/com/alibaba/nacos/ai/service/resource/AiResourceManager.java","lineNumber":1426,"sourceCode":"     */\n    @FunctionalInterface\n    public interface VersionStorageDeleter {\n        \n        void deleteStorage(AiResourceVersion version) throws NacosException;\n    }\n    \n    /**\n     * Delete meta and all version rows for a resource, invoking the given deleter for each version's storage.\n     */\n    public void deleteResourceWithVersions(String namespaceId, String name, String type,\n        VersionStorageDeleter storageDeleter) throws NacosException {\n        List<AiResourceVersion> versions = listAllVersions(namespaceId, name, type);\n        NacosException firstFailure = null;\n        for (AiResourceVersion v : versions) {\n            String version = v == null ? \"unknown\" : v.getVersion();\n            try {\n                if (v == null || StringUtils.isBlank(version)) {\n                    throw new NacosException(NacosException.SERVER_ERROR,\n                        \"AI resource Version row is invalid: \" + name);\n                }\n                storageDeleter.deleteStorage(v);\n            } catch (Exception e) {\n                NacosException failure = e instanceof NacosException ? (NacosException) e\n                    : new NacosException(NacosException.SERVER_ERROR,\n                        \"Failed to delete AI resource storage: \" + name + '@' + version, e);\n                if (firstFailure == null) {\n                    firstFailure = failure;\n                } else {\n                    firstFailure.addSuppressed(failure);\n                }\n            }\n        }\n        if (firstFailure != null) {\n            throw firstFailure;\n        }\n        aiResourcePersistService.delete(namespaceId, name, type);","sourceCodeStart":1408,"sourceCodeEnd":1444,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/ai/src/main/java/com/alibaba/nacos/ai/service/resource/AiResourceManager.java#L1408-L1444","documentation":"A SERVER_ERROR (HTTP 500) thrown by deleteResourceWithVersions when a listed version row is null or its version column is blank. It signals corrupt or half-inserted data rather than a caller mistake: normal API usage cannot create such a row. Per-version failures are collected and the first is rethrown (others attached via addSuppressed), so the trace lists every bad row.","triggerScenarios":"Deleting a skill/prompt/agentSpec whose ai_resource_version table contains a row with null version or a null row object; reached via SkillOperationServiceImpl.deleteSkill, PromptOperationServiceImpl, or AgentSpecOperationServiceImpl delete paths.","commonSituations":"A failed schema migration that left orphaned/null version rows; manual SQL edits against the version table; a crashed earlier write that inserted the meta but not the version column; a storage-dialect plugin bug producing null versions.","solutions":["Query ai_resource_version for the named resource and find rows where version IS NULL or the row is malformed; backfill or delete them.","Check the server log for the suppressed exceptions to see every offending row/version.","If no manual data corruption exists, file a bug — this path indicates a data-integrity defect, not user input.","Re-run the delete after cleanup."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    skillOp.deleteSkill(ns, name);\n} catch (NacosException e) {\n    if (e.getErrCode() == NacosException.SERVER_ERROR\n            && e.getErrMsg().contains(\"Version row is invalid\")) {\n        // data-integrity defect: alert ops, inspect ai_resource_version for null version rows\n        alertOpsCorruptVersionRows(ns, name, e.getSuppressed());\n    } else {\n        throw e;\n    }\n}","preventionTips":["Never manually insert or null-out the version column of ai_resource_version.","Validate migrations backfill non-null version values before going live.","Monitor for null/blank version rows as a data-health check.","Keep DB writes transactional so meta and version rows commit together."],"tags":["data-integrity","server-error","delete","corruption","ai-resource"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}