{"record":{"id":"4a2f2ece21a1d7e3","repo":"apache/iceberg","slug":"unable-to-list-directory","errorCode":null,"errorMessage":"Unable to list directory {}","messagePattern":"Unable to list directory (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"core/src/main/java/org/apache/iceberg/hadoop/HadoopCatalog.java","lineNumber":182,"sourceCode":"      return false;\n    } catch (IOException e) {\n      if (shouldSuppressPermissionError(e)) {\n        LOG.warn(\"Unable to list metadata directory {}\", metadataPath, e);\n        return false;\n      } else {\n        throw new UncheckedIOException(e);\n      }\n    }\n  }\n\n  private boolean isDirectory(Path path) {\n    try {\n      return fs.getFileStatus(path).isDirectory();\n    } catch (FileNotFoundException e) {\n      return false;\n    } catch (IOException e) {\n      if (shouldSuppressPermissionError(e)) {\n        LOG.warn(\"Unable to list directory {}\", path, e);\n        return false;\n      } else {\n        throw new UncheckedIOException(e);\n      }\n    }\n  }\n\n  @Override\n  public List<TableIdentifier> listTables(Namespace namespace) {\n    Preconditions.checkArgument(\n        namespace.levels().length >= 1, \"Missing database in table identifier: %s\", namespace);\n\n    Path nsPath = new Path(warehouseLocation, SLASH.join(namespace.levels()));\n    Set<TableIdentifier> tblIdents = Sets.newHashSet();\n\n    try {\n      if (!isDirectory(nsPath)) {\n        throw new NoSuchNamespaceException(\"Namespace does not exist: %s\", namespace);","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/hadoop/HadoopCatalog.java#L164-L200","documentation":"HadoopCatalog.isDirectory logs this WARN when fs.getFileStatus(path) throws an IOException classified as a permission error while checking whether a namespace path is a directory. The method returns false instead of throwing, so namespaces that cannot be stat'ed are silently skipped during listing operations.","triggerScenarios":"listTables or isNamespace calls isDirectory on a database/path; the filesystem returns an access-denied IOException and suppression of permission errors is enabled.","commonSituations":"Namespace directory owned by another user/group; missing execute bit on parent directories in HDFS; S3 bucket policy denying HEAD/GetObject on the prefix.","solutions":["Grant the calling user read/execute on the namespace directory path.","Correct HDFS ACLs or S3 IAM/bucket policy to allow stat operations.","Tune the permission-error suppression setting if these errors should be fatal instead of skipped."],"exampleFix":"// before\nhdfs dfs -ls /warehouse/otherdb  # Permission denied\n// after\nsudo hdfs dfs -chown -R catalog_user /warehouse/otherdb\n# or: hdfs dfs -setfacl -R -m user:catalog_user:r-x /warehouse/otherdb","handlingStrategy":"validation","validationCode":"// verify namespace dir accessibility before catalog operations\n// hadoop fs -test -d /warehouse/db && hadoop fs -ls /warehouse/db","typeGuard":null,"tryCatchPattern":"try {\n  catalog.listTables(namespace);\n} catch (UncheckedIOException e) {\n  LOG.error(\"Cannot stat namespace dir: {}\", e.getCause());\n}","preventionTips":["Ensure execute permission on all parent directories of namespaces.","Fix S3 bucket policies to allow HeadObject/ListBucket on prefixes.","Use a single service account with consistent ACLs across the warehouse."],"tags":["hadoop","permissions","io"],"backgroundTag":"permission-denied","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}