# stdin\_reader.takeDelimiterExclusive returns immediately in a loop instead of blocking for input (Zig 0.16, new Io interface)

**URL:** <https://ziggit.dev/t/stdin-reader-takedelimiterexclusive-returns-immediately-in-a-loop-instead-of-blocking-for-input-zig-0-16-new-io-interface/16923>\
**Category:** Help\
**Tags:** language, standard-library\
**Created:** [July 25, 2026, 3:04pm UTC](https://ziggit.dev/t/stdin-reader-takedelimiterexclusive-returns-immediately-in-a-loop-instead-of-blocking-for-input-zig-0-16-new-io-interface/16923 "2026-07-25T15:04:44Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![regpacy](https://ziggit.dev/user_avatar/ziggit.dev/regpacy/32/9721_2.png) [@regpacy](https://ziggit.dev/u/regpacy)\
**Post date:** [July 25, 2026, 3:04pm UTC](https://ziggit.dev/t/stdin-reader-takedelimiterexclusive-returns-immediately-in-a-loop-instead-of-blocking-for-input-zig-0-16-new-io-interface/16923/1 "2026-07-25T15:04:44Z")

</div>

I’m building a simple REPL using the new `std.Io` reader/writer interface in Zig 0.16. The loop is supposed to print a prompt, then block waiting for a line of input:

```zig
const std = @import("std");
const Io = std.Io;
pub fn main(init: std.process.Init) !void {
    const arena: std.mem.Allocator = init.arena.allocator();
    const io = init.io;
    _ = try init.minimal.args.toSlice(arena);

    var stdout_buffer: [1024]u8 = undefined;
    var stdout_file_writer: Io.File.Writer = .init(.stdout(), io, &stdout_buffer);
    const stdout_writer = &stdout_file_writer.interface;

    var stdin_buffer: [1024]u8 = undefined;
    var stdin_file_reader: Io.File.Reader = .init(.stdin(), io, &stdin_buffer);
    const stdin_reader = &stdin_file_reader.interface;
    while (true) {
        try stdout_writer.print("db > ", .{});
        try stdout_writer.flush();
        _ = try stdin_reader.takeDelimiterExclusive('\n');
    }
}

```

```zig
PS C:\Users\user\CLionProjects\project> .\zig-out\bin\project.exe
db > example
db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db > db 

```

Zig 0.16 Windows, same issue with wsl

---

<div class="post-metadata">

**Author:** ![pachde](https://ziggit.dev/user_avatar/ziggit.dev/pachde/32/2485_2.png) [@pachde](https://ziggit.dev/u/pachde)\
**Post date:** [July 25, 2026, 3:14pm UTC](https://ziggit.dev/t/stdin-reader-takedelimiterexclusive-returns-immediately-in-a-loop-instead-of-blocking-for-input-zig-0-16-new-io-interface/16923/2 "2026-07-25T15:14:08Z")

</div>

To progress, you must ‘take’ (or drop) that delimiter you excluded.

---

<div class="post-metadata">

**Author:** ![idkravitz](https://ziggit.dev/user_avatar/ziggit.dev/idkravitz/32/9189_2.png) [@idkravitz](https://ziggit.dev/u/idkravitz)\
**Post date:** [July 25, 2026, 3:20pm UTC](https://ziggit.dev/t/stdin-reader-takedelimiterexclusive-returns-immediately-in-a-loop-instead-of-blocking-for-input-zig-0-16-new-io-interface/16923/3 "2026-07-25T15:20:12Z")

</div>

its not an issue since this behaviour is described in documentation  
[https://ziglang.org/documentation/0.16.0/std/#std.Io.Reader.takeDelimiterExclusive](https://ziglang.org/documentation/0.16.0/std/#std.Io.Reader.takeDelimiterExclusive)

you should probably look at [Zig Documentation](https://ziglang.org/documentation/0.16.0/std/#std.Io.Reader.takeDelimiter)  
for the behaviour you expect

---

<div class="post-metadata">

**Author:** ![regpacy](https://ziggit.dev/user_avatar/ziggit.dev/regpacy/32/9721_2.png) [@regpacy](https://ziggit.dev/u/regpacy)\
**Post date:** [July 25, 2026, 3:24pm UTC](https://ziggit.dev/t/stdin-reader-takedelimiterexclusive-returns-immediately-in-a-loop-instead-of-blocking-for-input-zig-0-16-new-io-interface/16923/4 "2026-07-25T15:24:24Z")

</div>

thank you so much  
\_ = try stdin\_reader.takeDelimiterInclusive(‘\n’);  
changing Exclusive to Inclusive solved the problem

---

<div class="post-metadata">

**Author:** ![Fitti](https://ziggit.dev/user_avatar/ziggit.dev/fitti/32/7412_2.png) [@Fitti](https://ziggit.dev/u/Fitti)\
**Post date:** [July 26, 2026, 5:33am UTC](https://ziggit.dev/t/stdin-reader-takedelimiterexclusive-returns-immediately-in-a-loop-instead-of-blocking-for-input-zig-0-16-new-io-interface/16923/5 "2026-07-26T05:33:01Z")

</div>

Consider also just using [`takeDelimiter('\n')`](https://ziglang.org/documentation/master/std/#std.Io.Reader.takeDelimiter) instead:

> Returns a slice of the next bytes of buffered data from the stream until `delimiter` is found, advancing the seek position past the delimiter.

The differences are that `takeDelimiterInclusive` gives you the delimiter, `takeDelimiterExclusive` stops right before it, and `takeDelimiter` doesn’t give you the delimiter, but does move past it, which is often the most useful function.

Edit: So that means that `takeDelimiter` gives you `"example"`, while `takeDelimiterInclusive` gives you `"example\n"`.

---

<div class="post-metadata">

**Author:** ![truly-not-taken](https://ziggit.dev/user_avatar/ziggit.dev/truly-not-taken/32/6205_2.png) [@truly-not-taken](https://ziggit.dev/u/truly-not-taken)\
**Post date:** [July 26, 2026, 11:04am UTC](https://ziggit.dev/t/stdin-reader-takedelimiterexclusive-returns-immediately-in-a-loop-instead-of-blocking-for-input-zig-0-16-new-io-interface/16923/6 "2026-07-26T11:04:36Z")

</div>

Another difference is what happens at EndOfStream. `takeDelimiterInclusive('\n')` does not return the last line if there is no `'\n'` after it.

```Zig
test {
    var r: std.Io.Reader = .fixed("example");
    try std.testing.expectEqual(error.EndOfStream, r.takeDelimiterInclusive('\n'));
}

```
