{"record":{"id":"4bef0d5816b50a49","repo":"google/ExoPlayer","slug":"couldn-t-create-basename","errorCode":null,"errorMessage":"Couldn't create {baseName}","messagePattern":"Couldn't create (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"library/common/src/main/java/com/google/android/exoplayer2/util/AtomicFile.java","lineNumber":116,"sourceCode":"   */\n  public OutputStream startWrite() throws IOException {\n    // Rename the current file so it may be used as a backup during the next read\n    if (baseName.exists()) {\n      if (!backupName.exists()) {\n        if (!baseName.renameTo(backupName)) {\n          Log.w(TAG, \"Couldn't rename file \" + baseName + \" to backup file \" + backupName);\n        }\n      } else {\n        baseName.delete();\n      }\n    }\n    OutputStream str;\n    try {\n      str = new AtomicFileOutputStream(baseName);\n    } catch (FileNotFoundException e) {\n      File parent = baseName.getParentFile();\n      if (parent == null || !parent.mkdirs()) {\n        throw new IOException(\"Couldn't create \" + baseName, e);\n      }\n      // Try again now that we've created the parent directory.\n      try {\n        str = new AtomicFileOutputStream(baseName);\n      } catch (FileNotFoundException e2) {\n        throw new IOException(\"Couldn't create \" + baseName, e2);\n      }\n    }\n    return str;\n  }\n\n  /**\n   * Call when you have successfully finished writing to the stream returned by {@link\n   * #startWrite()}. This will close, sync, and commit the new data. The next attempt to read the\n   * atomic file will return the new file stream.\n   *\n   * @param str Outer-most wrapper OutputStream used to write to the stream returned by {@link\n   *     #startWrite()}.","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/google/ExoPlayer/blob/dd430f7053a1a3958deea3ead6a0565150c06bfc/library/common/src/main/java/com/google/android/exoplayer2/util/AtomicFile.java#L98-L134","documentation":"Thrown by AtomicFile.startWrite() when opening the base file for output raises FileNotFoundException and either the file has no parent directory or parent.mkdirs() fails to create it. AtomicFile implements write-then-rename atomic persistence (used for example by StandaloneMediaClock/DownloadManager/DatabaseProvider caches), and this error means it cannot even obtain a writable target file. Typical causes are missing storage permissions, a parent path that exists as a regular file, or read-only/missing external storage.","triggerScenarios":"Calling AtomicFile.startWrite() where baseName's parent directory does not exist and mkdirs() returns false: parent path occupied by a regular file, no WRITE permission for the location, external storage unmounted (path like /storage/emulated/0/... unavailable), or disk full/quota enforcing mkdir failure.","commonSituations":"App targeting API 30+ without properly scoped storage access writing to a shared directory; device USB-unmounted sdcard; the cache/data directory wiped or made read-only; path built from an environment variable (getExternalStorageDirectory) that is stale on newer Android versions.","solutions":["Check and request the correct storage permission (WRITE_EXTERNAL_STORAGE pre-API 30, or use app-private Context.getFilesDir()/getCacheDir() which needs no permission)","Verify the parent directory: ensure no regular file exists at the parent path, then call parent.mkdirs() yourself and log File.getCanonicalPath() and canWrite() before startWrite()","Use context-qualified paths (context.filesDir, context.cacheDir, or MediaStore API for shared storage) instead of hardcoded /sdcard paths","Free space / re-mount storage and retry the write once the environment check passes"],"exampleFix":"// before\nAtomicFile file = new AtomicFile(new File(\"/sdcard/myapp/state.bin\"));\nOutputStream os = file.startWrite(); // may throw IOException\n// after\nFile dir = new File(context.getFilesDir(), \"state\");\nif (!dir.exists() && !dir.mkdirs()) throw new IOException(\"Cannot mkdirs \" + dir);\nAtomicFile file = new AtomicFile(new File(dir, \"state.bin\"));\nOutputStream os = file.startWrite();","handlingStrategy":"validation","validationCode":"File dir = baseFile.getParentFile();\nif (dir == null || (!dir.exists() && !dir.mkdirs()) || !dir.canWrite()) {\n  // pick app-private storage or fail early with a clear message\n}","typeGuard":null,"tryCatchPattern":"catch (IOException e) { Log.w(TAG, \"Cannot persist state to \" + file, e); /* fall back to in-memory state */ }","preventionTips":["Always build AtomicFile paths under Context.getFilesDir()/getCacheDir()","Run canWrite() and a StatFs free-space check before startWrite()","Keep a last-known-good copy: AtomicFile's .new/.bak mechanics only help if you finishWrite() successfully"],"tags":["io","filesystem","storage","atomic-file"],"backgroundTag":null,"analyzedSha":"dd430f7053a1a3958deea3ead6a0565150c06bfc","analyzedAt":"2026-08-14T12:22:02.982Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}