Largest message size for XChaCha20-Poly1305 libsodium documentation says that XChaCha20-Poly1305 can encrypt a message of arbitrary size.

However, the only specification available (still a draft) explains that under the hood the IETF version of ChaCha20-Poly1305 is used (in combination with HChaCha20 for key derivation), which implies at the very least a hard limit of 256GB because of the 32 bit counter.

Who is right, and how large can a message be at most to be safely encrypted with XChaCha20-Poly1305?

And what about the authenticated data?
You should email the libsodium maintainers and the internet-draft author and ask them to talk to each other to work out what they mean, and to clearly document the limits in the internet-draft.  (They sometimes post here but not often.)

In principle, XChaCha provides $2^{256}$ 512-bit blocks of output under a single key, indexed by a 256-bit input.  The only question is how they are carved up for messages vs. blocks within a message.


For the XSalsa20 stream cipher, the message number is 192 bits, and the block number is the remaining 64 bits, so the theoretical limit on the number of blocks per message is $2^{64}$, or $2^{70}$ bytes.
For the Salsa20 stream cipher as in eSTREAM and as in NaCl, and for the related ChaCha stream cipher, the message number is 64 bits and the block number is the remaining 64 bits, so again the limit on blocks per message is $2^{64}$.
For the IETF ChaCha stream cipher of RFC 7539, the message number is 96 bits and the block number is 32 bits, so messages are limited to 256 GB.
The current XChaCha-Poly1305 internet-draft, draft-arciszewski-xchacha-03, is defined in terms of the IETF ChaCha-Poly1305 AEAD of RFC 7539 as a subroutine, in §2, p. 3, but it follows the XSalsa20 API, so the message number—which is a parameter to the API—is 192 bits, but the block number—which is managed internally by the API—is 32 bits; the remaining 32 bits of the internal ChaCha input are fixed to zero.
In what libsodium seems to implement for crypto_aead_xchacha20poly1305_ietf, according to the XChaCha20-Poly1305 construction page (archived 2019-05-30) and the AEAD limitations table (archived 2018-11-07), the message number is 192 bits and the block number is 64 bits, like XSalsa20.


If the byte order of the block number is chosen appropriately, this should be compatible with draft-arciszewski-xchacha-03 in the sense that it can correctly implement any protocol following the internet-draft, but it also allows much larger messages that are not allowed by the internet-draft.
It is also possible that the block number encoding is mismatched so that libsodium's crypto_aead_xchacha20poly1305_ietf is incompatible with draft-arciszewski-xchacha-03—I haven't checked.



All that said, the distinction between a 32-bit block number and a 64-bit block number is essentially academic: the largest message any implementation is willing to receive is the largest amount of memory that an adversary waste in a denial of service before you can drop the message on the floor.  It is hard to imagine applications for which this amount should reasonably be beyond a few megabytes, let alone 256 GB—larger messages can simply be broken up into smaller pieces at negligible additional cost since the per-piece overhead is at most a few dozen bytes, even if you include the 192-bit nonce and some formatting metadata.