Skip to content

open("/sd/.<filename>", "w") silently succeeds but file is never written on FAT32 volume #10981

@tim-oe

Description

@tim-oe

CircuitPython version and board name

Adafruit CircuitPython 10.2.0 on 2026-04-22; Adafruit Feather ESP32 V2 with ESP32
Board ID: adafruit_feather_esp32_v2

Code/REPL

`boot.py` mounts a FAT32 microSD card at `/sd` (Adalogger FeatherWing, SPI, CS on `board.D33`). The reproducer then writes a file whose name begins with a `.`:


import os

# Confirm /sd is mounted and writable
with open("/sd/normal_file.txt", "w") as f:
    f.write("hello\n")
    f.flush()

# Write a leading-dot filename to the same volume
with open("/sd/.hidden_file.txt", "w") as f:
    f.write("hello dot\n")
    f.flush()

# Check what actually landed on disk
print("listdir('/sd') =", os.listdir("/sd"))

# Attempt to read both back
for name in ("normal_file.txt", ".hidden_file.txt"):
    try:
        with open("/sd/" + name) as f:
            print(f"  {name}: {f.read()!r}")
    except OSError as exc:
        print(f"  {name}: OSError {exc}")

Behavior

listdir('/sd') = ['normal_file.txt']     # .hidden_file.txt is absent
  normal_file.txt: 'hello\n'
  .hidden_file.txt: OSError [Errno 2] No such file/directory

No exception is raised during the open(..., "w") or f.write() or f.flush() calls for the dot-file. The code appears to succeed, but the file is never written to the FAT directory. It does not appear in os.listdir() and cannot be read back.

Description

Expected behavior

Either:

  1. The write succeeds and the file appears in os.listdir("/sd") (correct POSIX behaviour — FAT32 has no concept of hidden dot-files; it uses a separate attribute flag), or
  2. An OSError is raised at open("/sd/.hidden_file.txt", "w") so the caller knows the write failed.

Silent success with no data written is never acceptable.

Diagnosis

FAT LFN (Long File Name) entries should preserve leading dots — .hidden_file.txt is a valid LFN. The FatFS library itself handles LFN correctly. The bug is likely in CircuitPython's VfsFat Python binding layer or in how it converts a Python filename string into an FatFS path before calling f_open. The leading dot may be stripped, normalised to an 8.3 short name that conflicts, or rejected by a filter that silently returns FR_OK instead of an error.

Workaround

Use a filename without a leading dot:

# BROKEN — silent data loss
with open("/sd/.sd_capacity", "w") as f:
    f.write("15931539456")

# WORKS
with open("/sd/sd_capacity.txt", "w") as f:
    f.write("15931539456")

Impact

Silent data loss. Any code that writes configuration, cache, or sentinel files with dot-prefixed names (a common Unix convention) will believe the write succeeded while the file is never actually stored. This is particularly dangerous in boot.py — the one place where writes happen before code.py gets control — because there is no feedback path to the user if the write silently fails.

Additional information

Hardware

Related

  • Adafruit CircuitPython issue #XXXX — os.statvfs("/sd") returns root VFS stats (same VfsFat layer, separate bug)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions