FileException Inconsistency?

Steven Schveighoffer schveiguy at gmail.com
Tue May 12 02:07:17 UTC 2026


On Monday, 11 May 2026 at 04:18:33 UTC, Alex wrote:
> Hi,
>
> After too many years of thinking to try D, I'm creating a 
> simple directory scanner.  However, I'm already getting some 
> "inconistencies" in Exception handling I'm confused by and 
> trying to debug.
>
> I'm using Visual D on Windows. DMD 2.110
>
> In the code below, if I leave the writeln(entry.name) or even 
> just writeln(".") uncommented, then I get a FileException for 
> permission-denied directories as expected.
>
> If I comment these lines out, e.g. to add the entry.name to an 
> array, instead I get a Throwable std.file.FileException which 
> is not caught as a FileException or Exception.
>
> Is this expected?  How to best handle this?
>
> Thanks
>
> ```
> module DirScan;
>
> import std.stdio;
> import std.file;
> import std.algorithm;
> import std.array;
> import core.thread;
>
> import std.compiler;
>
> int main()
> {
>     writeln("DirScan\n");
>     writefln("Compiler: %s v%d.%03d", name, version_major, 
> version_minor);
>
>     string path = "C:\\";
>
>     scan(path);
>
>     writeln("End. Press Enter.");
>     readln();
>     return 0;
> }
>
> void scan(string path)
> {
>     writeln("-----");
>     writeln("PATH: ", path);
>
>     foreach (DirEntry entry; dirEntries(path, SpanMode.shallow))
>     {
>         try
>         {
>             writeln(entry.name);
>             writeln(".");
>
>             if (entry.isDir)
>                 scan(entry.name);
>         }
>         catch (FileException fe) {
>             writeln("File Exception: ", fe);
>             readln();
>             continue;
>         }
>         catch (Exception e) {
>             writeln("Exception: ", e);
>             readln();
>             continue;
>         }
>         catch (Throwable t) {
>             writeln("Throwable: ", t);
>             readln();
>             return;
>         }
>     }
> }
> ```

If you are seeing "Throwable: std.file.FileException", then I 
suggest one of two things are true:

1. You are misreading the error.
2. The code above + edits you have outlined is not what you are 
actually executing.

Sorry, but these are the only two options I see here. The above 
doesn't seem like it should ever fail differently if you change 
`writeln` calls (I tested locally with the exact steps, and I 
don't see the issue you identify). I am often also guilty of 
trying to "simplify" things for posting on the forums. Almost 
inevitably, I have missed some typo or some interpretation.

The generated code that handles exception catching is rock-solid, 
and decades old. I don't believe there would be an issue with it.

I suggest posting the code that *doesn't* work, and also the 
output when that command is given which is not as you expect. 
It's OK to truncate the output to the problem area (I imagine 
there's quite a bit of your hard drive structure in there), but 
at least show what is printed surrounding the error.

At the very least, this should allow people to reproduce the 
issue.

e.g. on my mac system, I modified your code a bit:

```d
module DirScan;

import std.stdio;
import std.file;
import std.algorithm;
import std.array;
import core.thread;

import std.compiler;

int main()
{
     writeln("DirScan\n");
     writefln("Compiler: %s v%d.%03d", name, version_major, 
version_minor);

     string path = "./";

     scan(path);

     writeln("End. Press Enter.");
     readln();
     return 0;
}

void scan(string path)
{
     writeln("-----");
     writeln("PATH: ", path);

     foreach (DirEntry entry; dirEntries(path, SpanMode.shallow))
     {
         try
         {
             //writeln(entry.name);
             //writeln(".");

             if (entry.isDir)
                 scan(entry.name);
         }
         catch (FileException fe) {
             writeln("File Exception: ", fe);
             readln();
             continue;
         }
         catch (Exception e) {
             writeln("Exception: ", e);
             readln();
             continue;
         }
         catch (Throwable t) {
             writeln("Throwable: ", t);
             readln();
             return;
         }
     }
}
```

And then created a directory structure that is not readable:

```console
% ls -R .
foo		testme		testme.d	testme.o

./foo:
blah		blah.txt

./foo/blah:
ls: ./foo/blah: Permission denied
```

And this is the result I get:

```console
% ./testme
DirScan

Compiler: LDC v2.111
-----
PATH: ./
-----
PATH: ./foo
-----
PATH: ./foo/blah
File Exception: std.file.FileException at std/file.d(4752): 
./foo/blah: Permission denied
----------------
??:? @safe bool 
std.file.DirIteratorImpl.stepIn(immutable(char)[]) [0x104888a47]
??:? ref @safe std.file.DirIteratorImpl 
std.file.DirIteratorImpl.__ctor!(immutable(char)[]).__ctor(immutable(char)[], std.file.SpanMode, bool) [0x10487cb53]
??:? ref @safe 
core.internal.lifetime.emplaceRef!(std.file.DirIteratorImpl, 
std.file.DirIteratorImpl, immutable(char)[], std.file.SpanMode, 
bool).emplaceRef(ref std.file.DirIteratorImpl, ref 
immutable(char)[], ref std.file.SpanMode, ref bool).S 
core.internal.lifetime.emplaceRef!(std.file.DirIteratorImpl, 
std.file.DirIteratorImpl, immutable(char)[], std.file.SpanMode, 
bool).emplaceRef(ref std.file.DirIteratorImpl, ref 
immutable(char)[], ref std.file.SpanMode, ref 
bool).S.__ctor!().__ctor(ref immutable(char)[], ref 
std.file.SpanMode, ref bool) [0x10487caab]
??:? @safe void 
core.internal.lifetime.emplaceRef!(std.file.DirIteratorImpl, 
std.file.DirIteratorImpl, immutable(char)[], std.file.SpanMode, 
bool).emplaceRef(ref std.file.DirIteratorImpl, ref 
immutable(char)[], ref std.file.SpanMode, ref bool) [0x10487ca03]
??:? @safe std.file.DirIteratorImpl* 
core.lifetime.emplace!(std.file.DirIteratorImpl, 
immutable(char)[], std.file.SpanMode, 
bool).emplace(std.file.DirIteratorImpl*, ref immutable(char)[], 
ref std.file.SpanMode, ref bool) [0x10487c9a3]
??:? @safe void 
std.typecons.SafeRefCounted!(std.file.DirIteratorImpl, 
0).SafeRefCounted.RefCountedStore.initialize!(immutable(char)[], 
std.file.SpanMode, bool).initialize(ref immutable(char)[], ref 
std.file.SpanMode, ref bool) [0x10487c903]
??:? ref @safe 
std.typecons.SafeRefCounted!(std.file.DirIteratorImpl, 
0).SafeRefCounted 
std.typecons.SafeRefCounted!(std.file.DirIteratorImpl, 
0).SafeRefCounted.__ctor!(immutable(char)[], std.file.SpanMode, 
bool).__ctor(ref immutable(char)[], ref std.file.SpanMode, ref 
bool) [0x10487c53f]
??:? ref @trusted std.file._DirIterator!(false)._DirIterator 
std.file._DirIterator!(false)._DirIterator.__ctor(immutable(char)[], std.file.SpanMode, bool) [0x10487c4cb]
??:? std.file._DirIterator!(false)._DirIterator 
std.file.dirEntries!(false).dirEntries(immutable(char)[], 
std.file.SpanMode, bool) [0x104860eaf]
??:? void DirScan.scan(immutable(char)[]) [0x104860b73]
??:? void DirScan.scan(immutable(char)[]) [0x104860bdf]
??:? void DirScan.scan(immutable(char)[]) [0x104860bdf]
??:? _Dmain [0x10486095b]

End. Press Enter.
```

-Steve


More information about the Digitalmars-d-learn mailing list