laurent22/joplin · error · IOExceptionFast

could not create file at

Error message

could not create file at: ${unknownStr}

What it means

EfficientDocumentHelper.createFile throws "could not create file at: <path>" when the plain file:// scheme branch fails: File.createNewFile() returned false and the replaceIfDestinationExists fallback (existing regular file) did not apply. The OS-level file creation on the local filesystem failed, typically due to permissions or an invalid/unwritable parent path.

Solutions

  1. Use SAF content URIs (a document tree picked via openDocumentTree) instead of raw file:// paths.
  2. Verify the parent directory exists, is writable, and the destination is not an existing directory.
  3. Set replaceIfDestinationExists: true if the failure is due to an existing plain file.

Example fix

// before
await SafX.createFile('file:///storage/emulated/0/notes/x.txt', 'text/plain');
// after
const treeUri = await SafX.openDocumentTree();
await SafX.createFile(treeUri, 'x.txt', 'text/plain', { replaceIfDestinationExists: true });
Defensive patterns

Strategy: try-catch

Try / catch

try { await SafX.createFile(target, mime); } catch (e) { if (String(e.message).startsWith('could not create file')) switchToSafTreeUriFlow(); }

Prevention

When it happens

Trigger: createFile called with a file:// URI whose createNewFile() returns false (parent dir not writable, path invalid, or file exists but is a directory) while replaceIfDestinationExists is false.

Common situations: Targeting app-private or restricted storage locations without permission on newer Android versions; passing a directory path as the destination; external storage not mounted.

Understand the failure class

Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.

Related errors


AI-assisted analysis of laurent22/joplin@981a03c5c9 (2026-09-17). Data as JSON: /api/errors/ebd8bd34d503387e. Report an issue: GitHub.

Appendix: source

Thrown at packages/react-native-saf-x/android/src/main/java/com/reactnativesafx/utils/EfficientDocumentHelper.java:412

    try {
      uri = getDocumentUri(unknownStr, false, true);
    } catch (FileNotFoundException ignored) {
    }

    if (uri != null) {
      if (replaceIfDestinationExists) return uri;
      throw new IOExceptionFast("a file or directory already exist at: " + uri);
    }

    uri = UriHelper.getUnifiedUri(unknownStr);

    if (uri.getScheme().equals(ContentResolver.SCHEME_FILE)) {
      File file = new File(uri.getPath());
      file.getParentFile().mkdirs();
      boolean created = file.createNewFile();
      if (!created) {
        if (replaceIfDestinationExists && file.exists() && file.isFile()) return uri;
        throw new IOExceptionFast("could not create file at: " + unknownStr);
      }
      return uri;
    }

    Uri parentDirOfFile = getDocumentUri(unknownStr, true, false);

    String fileName = UriHelper.getFileName(unknownStr);
    return createFileInDirectory(parentDirOfFile, fileName, mimeType, replaceIfDestinationExists);
  }

  private Uri createFileInDirectory(
    final Uri parentDirOfFile,
    final String fileName,
    final String mimeType,
    final boolean replaceIfDestinationExists
  ) throws IOException {
    if (fileName.indexOf(':') != -1) {
      throw new IOExceptionFast(

View on GitHub (pinned to 981a03c5c9)