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