{"record":{"id":"6df8d86341bb6268","repo":"apache/hadoop","slug":"the-trash-feature-fs-obs-trash-enable-is-enabled","errorCode":null,"errorMessage":"The trash feature(fs.obs.trash.enable) is enabled, but the configuration(fs.obs.trash.dir [%s]) is empty.","messagePattern":"The trash feature\\(fs\\.obs\\.trash\\.enable\\) is enabled, but the configuration\\(fs\\.obs\\.trash\\.dir \\[(.+?)\\]\\) is empty\\.","errorType":"exception","errorClass":"ObsException","httpStatus":null,"severity":"error","filePath":"hadoop-cloud-storage-project/hadoop-huaweicloud/src/main/java/org/apache/hadoop/fs/obs/OBSFileSystem.java","lineNumber":368,"sourceCode":"        if (!isFsBucket()) {\n          String errorMsg = String.format(\n              \"The bucket [%s] is not posix. not supported for \"\n                  + \"trash.\", bucket);\n          LOG.warn(errorMsg);\n          enableTrash = false;\n          trashDir = null;\n        } else {\n          trashDir = conf.get(OBSConstants.TRASH_DIR);\n          if (StringUtils.isEmpty(trashDir)) {\n            String errorMsg =\n                String.format(\n                    \"The trash feature(fs.obs.trash.enable) is \"\n                        + \"enabled, but the \"\n                        + \"configuration(fs.obs.trash.dir [%s]) \"\n                        + \"is empty.\",\n                    trashDir);\n            LOG.error(errorMsg);\n            throw new ObsException(errorMsg);\n          }\n          trashDir = OBSCommonUtils.maybeAddBeginningSlash(trashDir);\n          trashDir = OBSCommonUtils.maybeAddTrailingSlash(trashDir);\n        }\n      }\n    } catch (ObsException e) {\n      throw OBSCommonUtils.translateException(\"initializing \",\n          new Path(name), e);\n    }\n  }\n\n  private void initThreadPools(final Configuration conf) {\n    long keepAliveTime = OBSCommonUtils.longOption(conf,\n        OBSConstants.KEEPALIVE_TIME,\n        OBSConstants.DEFAULT_KEEPALIVE_TIME, 0);\n\n    int maxThreads = conf.getInt(OBSConstants.MAX_THREADS,\n        OBSConstants.DEFAULT_MAX_THREADS);","sourceCodeStart":350,"sourceCodeEnd":386,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-cloud-storage-project/hadoop-huaweicloud/src/main/java/org/apache/hadoop/fs/obs/OBSFileSystem.java#L350-L386","documentation":"During OBSFileSystem.initialize, when fs.obs.trash.enable is true the connector reads fs.obs.trash.dir and requires a non-empty value; empty/missing triggers an ObsException with this message (afterwards normalized by translateException during propagation). The trash feature needs an explicit directory to move deleted objects to — there is no default — so enabling it without configuring the destination leaves the filesystem unusable. Initialization fails before any operation can run.","triggerScenarios":"Setting fs.obs.trash.enable=true in core-site.xml while fs.obs.trash.dir is absent, empty, or whitespace; enabling trash via programmatic Configuration(conf.setBoolean) but forgetting conf.set for the dir; XML templating that renders the trash.dir property with an empty ${variable}.","commonSituations":"Teams copying a partial OBS configuration snippet that lists trash.enable but not trash.dir; environment-specific configs where the trash directory variable is only defined in one environment; upgrades where trash was newly enabled without completing the config pair.","solutions":["Set fs.obs.trash.dir to a valid OBS path (e.g. /user/.Trash) whenever fs.obs.trash.enable=true","Or set fs.obs.trash.enable=false (or remove it) if soft-delete behavior is not wanted","Validate the configuration pair at deploy time with a smoke test that mounts the filesystem before jobs launch","If configuring programmatically, assert both keys together: if enable is true, require non-empty dir before calling FileSystem.get"],"exampleFix":"// before\nconf.setBoolean(\"fs.obs.trash.enable\", true);\n// fs.obs.trash.dir missing -> ObsException at initialize\n\n// after\nconf.setBoolean(\"fs.obs.trash.enable\", true);\nconf.set(\"fs.obs.trash.dir\", \"/user/.Trash\");","handlingStrategy":"validation","validationCode":"boolean trashEnabled = conf.getBoolean(\"fs.obs.trash.enable\", false);\nString trashDir = conf.get(\"fs.obs.trash.dir\");\nif (trashEnabled && (trashDir == null || trashDir.trim().isEmpty())) {\n  throw new IllegalStateException(\n      \"fs.obs.trash.dir must be set when fs.obs.trash.enable=true\");\n}\n// only then construct the OBS FileSystem","typeGuard":null,"tryCatchPattern":"try {\n  FileSystem fs = path.getFileSystem(conf);\n} catch (IOException e) {\n  if (String.valueOf(e.getMessage()).contains(\"fs.obs.trash.dir\")) {\n    // configuration error: set fs.obs.trash.dir or disable trash, then retry mount\n  }\n  throw e;\n}","preventionTips":["Treat trash.enable and trash.dir as an inseparable config pair in templates","Fail fast in deploy scripts on half-configured features","Smoke-test the mount step before submitting jobs"],"tags":["configuration","initialization","trash","hadoop-obs"],"backgroundTag":"missing-configuration-key","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}