{"record":{"id":"e9ab62d938df5f7c","repo":"apache/dolphinscheduler","slug":"invalidated-resource-path-resourceabsolutepath","errorCode":null,"errorMessage":"Invalidated resource path: ${resourceAbsolutePath}","messagePattern":"Invalidated resource path: (.+?)","errorType":"validation","errorClass":"ServiceException","httpStatus":null,"severity":"error","filePath":"dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/validator/resource/AbstractResourceValidator.java","lineNumber":61,"sourceCode":"\n    private static final Set<String> FILE_SUFFIXES_WHICH_CAN_FETCH_CONTENT = new HashSet<>(Arrays.asList(\n            StringUtils.defaultIfBlank(FileUtils.getResourceViewSuffixes(), \"\").split(\",\")));\n\n    protected final StorageOperator storageOperator;\n\n    private final TenantDao tenantDao;\n\n    public AbstractResourceValidator(StorageOperator storageOperator, TenantDao tenantDao) {\n        this.storageOperator = storageOperator;\n        this.tenantDao = tenantDao;\n    }\n\n    public void exceptionResourceAbsolutePathInvalidated(String resourceAbsolutePath) {\n        if (StringUtils.isBlank(resourceAbsolutePath)) {\n            throw new ServiceException(\"The resource path is null\");\n        }\n        if (!resourceAbsolutePath.startsWith(storageOperator.getStorageBaseDirectory())) {\n            throw new ServiceException(\"Invalidated resource path: \" + resourceAbsolutePath);\n        }\n        if (resourceAbsolutePath.contains(\"..\")) {\n            throw new ServiceException(\"Invalidated resource path: \" + resourceAbsolutePath);\n        }\n    }\n\n    public void exceptionFileInvalidated(MultipartFile file) {\n        if (file == null) {\n            throw new ServiceException(\"The file is null\");\n        }\n    }\n\n    public void exceptionFileContentInvalidated(String fileContent) {\n        if (StringUtils.isEmpty(fileContent)) {\n            throw new ServiceException(\"The file content is null\");\n        }\n    }\n","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/validator/resource/AbstractResourceValidator.java#L43-L79","documentation":"After the blank check, exceptionResourceAbsolutePathInvalidated verifies the path starts with storageOperator.getStorageBaseDirectory() (the configured storage root, e.g. the HDFS/S3 base dir). A path outside the configured storage base is rejected with ServiceException(\"Invalidated resource path: ...\"). This prevents accessing resources outside DolphinScheduler-managed storage.","triggerScenarios":"Requesting a resource whose absolute path is not under the configured storage base directory - typically when the storage base configuration changed (resource.storage.type/base dir) after resources were created, or a client passes an arbitrary local/absolute path.","commonSituations":"Cluster migration from local storage to HDFS/S3 without moving data; resource.storage.base.dir updated in config while old paths persist in the DB; manually crafted API calls referencing paths on a different tenant root or storage system.","solutions":["Use the full path as returned by the resource-center listing API rather than constructing it manually.","Align resource.storage.* configuration with the actual base directory of stored resources.","Migrate/re-upload resources so their stored paths live under the current storage base directory."],"exampleFix":"// before\npath = \"/tmp/local-upload/script.sql\";           // outside storage base\n// after\npath = \"/dolphinscheduler/alice/resources/script.sql\"; // starts with storageOperator.getStorageBaseDirectory()","handlingStrategy":"validation","validationCode":"// client-side pre-check\nconst baseDir = storageBaseDirectory; // from server config / listing API\nif (!resourceAbsolutePath.startsWith(baseDir)) {\n    throw new IllegalArgumentException(\"path must be under storage base dir \" + baseDir);\n}","typeGuard":"function isInsideStorageBase(path, baseDir) {\n  return typeof path === 'string' && path.startsWith(baseDir.replace(/\\/$/, '') + '/');\n}","tryCatchPattern":"try {\n    // resource operation\n} catch (ServiceException e) {\n    if (e.getMessage().startsWith(\"Invalidated resource path:\")) {\n        // reload paths via the resource listing API; verify storage config\n    } else throw e;\n}","preventionTips":["Keep resource.storage.* config stable across restarts, or migrate data when changing it","After a storage-type migration, re-upload or relocate existing resources","Use API-returned paths, never hand-built absolute paths"],"tags":["resource","path-validation","storage-config"],"backgroundTag":"invalid-config-value","analyzedSha":"02eac45a1b6676e639fcbfb4be2243de5771b05d","analyzedAt":"2026-09-06T17:43:00.555Z","contentChangedAt":"2026-09-06T17:43:00.555Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}