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@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

Reply via email to