{"record":{"id":"49c52ef1d16f8b56","repo":"apache/hadoop","slug":"credentials-requested-after-provider-list-was-clos","errorCode":null,"errorMessage":"Credentials requested after provider list was closed","messagePattern":"Credentials requested after provider list was closed","errorType":"exception","errorClass":"NoAuthWithCOSException","httpStatus":null,"severity":"error","filePath":"hadoop-cloud-storage-project/hadoop-cos/src/main/java/org/apache/hadoop/fs/cosn/auth/COSCredentialsProviderList.java","lineNumber":92,"sourceCode":"    if (this.providers.isEmpty()) {\n      throw new NoAuthWithCOSException(NO_COS_CREDENTIAL_PROVIDERS);\n    }\n  }\n\n  public COSCredentialsProviderList share() {\n    Preconditions.checkState(!this.closed(), \"Provider list is closed\");\n    this.refCount.incrementAndGet();\n    return this;\n  }\n\n  public boolean closed() {\n    return this.isClosed.get();\n  }\n\n  @Override\n  public COSCredentials getCredentials() {\n    if (this.closed()) {\n      throw new NoAuthWithCOSException(CREDENTIALS_REQUESTED_WHEN_CLOSED);\n    }\n\n    this.checkNotEmpty();\n\n    if (this.reuseLastProvider && this.lastProvider != null) {\n      return this.lastProvider.getCredentials();\n    }\n\n    for (COSCredentialsProvider provider : this.providers) {\n      COSCredentials credentials = provider.getCredentials();\n      if (null != credentials\n           && !StringUtils.isNullOrEmpty(credentials.getCOSAccessKeyId())\n           && !StringUtils.isNullOrEmpty(credentials.getCOSSecretKey())\n           || credentials instanceof AnonymousCOSCredentials) {\n        this.lastProvider = provider;\n        return credentials;\n      }\n    }","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-cloud-storage-project/hadoop-cos/src/main/java/org/apache/hadoop/fs/cosn/auth/COSCredentialsProviderList.java#L74-L110","documentation":"COSCredentialsProviderList is refcounted: share() increments, close() decrements and marks the list closed when the last user releases it. getCredentials() on an already-closed list throws NoAuthWithCOSException(\"Credentials requested after provider list was closed\"). This is a lifecycle bug — some component holds/uses the credential chain beyond the lifetime of the filesystem that owned it.","triggerScenarios":"Calling getCredentials() (directly or via a store/stream still alive) after CosNFileSystem.close() released the last reference; double-closing a CosNFileSystem while background threads (upload part threads, read streams) still authenticate; caching a provider list across filesystem instances that then closes it.","commonSituations":"Not closing streams before closing the filesystem; jobs that reuse a cached FileSystem object after the owner task closed it; custom code that grabs the internal provider list and outlives the FS; shutdown ordering bugs in embedded usage.","solutions":["Close all streams and complete all operations before calling FileSystem.close() on the cosn instance","If sharing the filesystem across components, use FileSystem.get() caching so the same refcounted instance is reused instead of hand-managed lifetimes","Do not cache or export the internal COSCredentialsProviderList beyond the filesystem's lifetime","Audit for double-close paths — a second close() can drop the refcount to zero while workers still run"],"exampleFix":"// before\nFileSystem fs = path.getFileSystem(conf);\nFSDataInputStream in = fs.open(path);\nfs.close();               // refcount -> 0, list closed\nin.read();               // -> Credentials requested after provider list was closed\n\n// after\nFileSystem fs = path.getFileSystem(conf);\ntry (FSDataInputStream in = fs.open(path)) {\n  in.read();\n}\nfs.close();","handlingStrategy":"validation","validationCode":"// Guard the credential chain's lifecycle before use\nCOSCredentialsProviderList list = ...;\nif (list.closed()) {\n  // re-acquire the filesystem instead of using a dead chain\n  fs = FileSystem.get(uri, conf);\n}","typeGuard":null,"tryCatchPattern":"try {\n  fs.open(path);\n} catch (NoAuthWithCOSException e) {\n  if (String.valueOf(e.getMessage()).contains(\"provider list was closed\")) {\n    // lifecycle bug: someone closed the FileSystem while streams were alive\n    throw new IllegalStateException(\"cosn FileSystem used after close\", e);\n  }\n  throw e;\n}","preventionTips":["Close all FSDataInputStream/OutputStream instances before FileSystem.close()","Rely on FileSystem.get() caching rather than hand-managed lifetimes","Never cache the internal provider list beyond the owning filesystem"],"tags":["cosn","hadoop-cos","lifecycle","use-after-close","credentials"],"backgroundTag":"resource-used-after-close","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}