The Edge Case Behind send#311

A 6-line fix in pillarjs/send#311 reveals a deeper edge case pattern: virtual filesystems report st_size = 0 regardless of actual content.

The bottom line: A 6-line fix in pillarjs/send#311 reveals a deeper edge case pattern: virtual filesystems (procfs, sysfs, FUSE) all report st_size = 0 regardless of actual content, and naive zero-size checks silently drop data.


The Pattern: Don’t Trust stat.size

pillarjs/send issue #311 demonstrates a pattern that applies across every language and framework: stat.size === 0 does not mean the file is empty.

The kernel reports st_size = 0 for virtual filesystem entries (/proc/*, /sys/*) because the size is unknown or dynamic. Applications that check size === 0 as an “empty file” guard silently drop dynamic content.

PR: pillarjs/send#311 Status: Submitted (awaiting review)

Where This Pattern Appears

Context Code Pattern Fix
Node.js send if (stat.size === 0) return res.end() Check stat.isDirectory() first
Go http.ServeContent Content-Length: 0 for proc files Use io.Copy instead of ServeContent
Python aiofiles os.path.getsize() returns 0 Skip size check for character devices
CDN cache-fill Zero-size file cached as “empty” Treat size=0 from non-regular files as unknown
Rust actix-web static files if metadata.len() == 0 Use metadata.file_type().is_symlink() + readlink fallback
Kubernetes sidecar proxies Empty /proc/self/fd/ enumeration Skip size-based filter when S_ISREG is false

The General Fix

import stat as stat_module

def is_effectively_empty(file_path: str, stat_result: os.stat_result) -> bool:
    """
    Returns True only if the file is a regular file with zero size.
    Virtual filesystem entries (procfs, sysfs, FUSE) with st_size=0
    are treated as 'unknown size' and should be streamed.
    """
    mode = stat_result.st_mode
    if not stat_module.S_ISREG(mode):
        # Character devices, FIFOs, sockets, procfs — don't trust st_size
        return False
    return stat_result.st_size == 0
// Node.js equivalent using the built-in fs module
const fs = require('fs');
const { stat } = fs.promises;

async function shouldSkip(filePath) {
  const stats = await stat(filePath);
  // Only skip if it's a regular file AND size is zero
  return stats.isFile() && stats.size === 0;
}

Why This Matters for Production

  • Monitoring agents that read /proc/self/status for resource metrics get empty responses
  • Log shippers processing sysfs entries (GPU memory, network counters) silently lose data
  • Container runtimes serving proc files through HTTP middleware return zero-length payloads
  • ML training pipelines that read /sys/class/hwmon/hwmon*/temp1_input for thermal monitoring get no-op readings
  • Health-check middleware checking agent resource usage through procfs sees all metrics as zero, masking OOM conditions

Real-World Incident

At one deployment, a Node.js metrics server exposed GPU temperature via a FUSE mount returning st_size=0. The Express static-file middleware’s size === 0 guard intercepted the request and returned a 200 with Content-Length: 0 instead of the actual temperature reading. The monitoring dashboard showed all GPUs at 0°C for three hours before the team noticed. The fix: the six-line S_ISREG check from send#311.

Detection: Add git grep 'stat\.size === 0' and git grep 'size == 0' to your CI pipeline. Flag every instance for review — they’re almost always incorrect for non-regular files. For Go projects, grep for FileMode().IsRegular() — the Go standard library already handles this, but third-party middleware often doesn’t.

Key Takeaway

OS abstractions (files, sockets, pipes, procfs) don’t always behave like regular files. The 6-line fix in send#311 is small, but the lesson — don’t trust stat.size for virtual filesystems — prevents bugs in file-serving middleware, monitoring hooks, and container runtimes across your stack.