# Does Arrow.jl support enums?

**URL:** <https://discourse.julialang.org/t/does-arrow-jl-support-enums/89163>\
**Category:** New to Julia\
**Tags:** arrow\
**Created:** [October 23, 2022, 9:48pm UTC](https://discourse.julialang.org/t/does-arrow-jl-support-enums/89163 "2022-10-23T21:48:57Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![freeman](https://avatars.discourse-cdn.com/v4/letter/f/ec9cab/32.png) [@freeman](https://discourse.julialang.org/u/freeman)\
**Post date:** [October 23, 2022, 9:48pm UTC](https://discourse.julialang.org/t/does-arrow-jl-support-enums/89163/1 "2022-10-23T21:48:57Z")

</div>

I’m surprised that the code below doesn’t work.

```julia
@enum MyEnum LALA1 LALA2 LALA3
x = [LALA1, LALA1, LALA3, LALA2]
table = (cols1=x,)
io = IOBuffer()
Arrow.write(io, table)

```

```julia
ERROR: MethodError: no method matching arrowtype(::Arrow.FlatBuffers.Builder, ::Type{MyEnum})
Closest candidates are:
  arrowtype(::Any, ::Union{Arrow.DenseUnion{S, Arrow.UnionT{T, typeIds, U}}, Arrow.SparseUnion{S, Arrow.UnionT{T, typeIds, U}}}) where {S, T, typeIds, U} at ~/.julia/packages/Arrow/ZlMFU/src/eltypes.jl:484

```

It’s possible that enums by default require some interface method defined on them, but searching the docs for “enum” returns nothing.

---

<div class="post-metadata">

**Author:** ![freeman](https://avatars.discourse-cdn.com/v4/letter/f/ec9cab/32.png) [@freeman](https://discourse.julialang.org/u/freeman)\
**Post date:** [October 23, 2022, 10:09pm UTC](https://discourse.julialang.org/t/does-arrow-jl-support-enums/89163/2 "2022-10-23T22:09:54Z")

</div>

Ok so this does something

```julia
ArrowTypes.ArrowKind(::Type{MyEnum}) = ArrowTypes.DictEncodedKind
Arrow.write(io, table) # IOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=256, maxsize=Inf, ptr=257, mark=-1)

```

However, I still can’t read it back

```julia
seekstart(io)
table2 = Arrow.Table(io) # ERROR: type Nothing has no field fields

```

I also can’t make sense of the data that was actually written to the buffer

```julia
reinterpret(Int8, io.data)

```

I expected that the first 4 elements of this would be `[0, 0, 2, 1]`, but it’s all `-1`.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [October 23, 2022, 10:34pm UTC](https://discourse.julialang.org/t/does-arrow-jl-support-enums/89163/3 "2022-10-23T22:34:13Z")

</div>

ENUM are just integers, just use the values:

```julia
julia> @enum Fruit a b c

julia> Integer.([a,b,c])
3-element Vector{Int32}:
 0
 1
 2

# when you read back from Arrow, re-make the enums
julia> Fruit.(Integer.([a,b,c]))
3-element Vector{Fruit}:
 a::Fruit = 0
 b::Fruit = 1
 c::Fruit = 2

```

---

<div class="post-metadata">

**Author:** ![freeman](https://avatars.discourse-cdn.com/v4/letter/f/ec9cab/32.png) [@freeman](https://discourse.julialang.org/u/freeman)\
**Post date:** [October 23, 2022, 10:41pm UTC](https://discourse.julialang.org/t/does-arrow-jl-support-enums/89163/4 "2022-10-23T22:41:31Z")

</div>

I understand that, but I don’t want to do that. I want to do `Arrow.Table(io)` and get my objects properly deserialized. Of course I can cast manually, but that’s not what I want.

---

<div class="post-metadata">

**Author:** ![freeman](https://avatars.discourse-cdn.com/v4/letter/f/ec9cab/32.png) [@freeman](https://discourse.julialang.org/u/freeman)\
**Post date:** [October 23, 2022, 11:15pm UTC](https://discourse.julialang.org/t/does-arrow-jl-support-enums/89163/5 "2022-10-23T23:15:16Z")

</div>

Here’s another attempt

```julia
@enum MyEnum LALA1 LALA2 LALA3
ArrowTypes.arrowname(::Type{MyEnum}) = :MyEnum
ArrowTypes.JuliaType(::Val{:MyEnum}) = MyEnum
ArrowTypes.ArrowKind(::Type{MyEnum}) = ArrowTypes.PrimitiveKind
ArrowTypes.toarrow(::Type{MyEnum}) = Int
ArrowTypes.fromarrow(::Type{MyEnum}, x) = MyEnum(x) # shouldn't be necessary as this is the default
x = [LALA1, LALA1, LALA3, LALA2]
table = (cols1=x,)
io = IOBuffer()
Arrow.write(io, table)
seekstart(io)
table2 = Arrow.Table(io) # correctly reports 4 rows
table2.cols1

```

The last line returns

```julia
ERROR: MethodError: no method matching MyEnum()
Closest candidates are:
  MyEnum(::Integer) at Enums.jl:197

```

I don’t understand why it’s calling `MyEnum()`. I expected it t call `MyEnum(x)` where `x` is an `Int` it reads from the buffer.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [October 24, 2022, 1:56am UTC](https://discourse.julialang.org/t/does-arrow-jl-support-enums/89163/6 "2022-10-24T01:56:02Z")

</div>

> [@freeman](#):
>
> I understand that, but I don’t want to do that.

then you get what you get

---

<div class="post-metadata">

**Author:** ![dlakelan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dlakelan/32/8491_2.png) [@dlakelan](https://discourse.julialang.org/u/dlakelan)\
**Post date:** [October 24, 2022, 2:37am UTC](https://discourse.julialang.org/t/does-arrow-jl-support-enums/89163/7 "2022-10-24T02:37:13Z")

</div>

> [@freeman](#):
>
> I want to do `Arrow.Table(io)` and get my objects properly deserialized.

How do you propose that Arrow.jl will know that the file contains integers that refer to a particular Enum and not just integers that refer to numbers?

[https://arrow.apache.org/docs/python/api/datatypes.html](https://arrow.apache.org/docs/python/api/datatypes.html)

seems to be the data types Arrow understands.

---

<div class="post-metadata">

**Author:** ![digital\_carver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/digital_carver/32/33818_2.png) [@digital\_carver](https://discourse.julialang.org/u/digital_carver)\
**Post date:** [October 24, 2022, 7:15am UTC](https://discourse.julialang.org/t/does-arrow-jl-support-enums/89163/8 "2022-10-24T07:15:33Z")

</div>

> [@freeman](#):
>
> Here’s another attempt

```julia
using Arrow

@enum MyEnum LALA1 LALA2 LALA3

ArrowTypes.arrowname(::Type{MyEnum}) = :MyEnum
ArrowTypes.JuliaType(::Val{:MyEnum}) = MyEnum
ArrowTypes.ArrowKind(::Type{MyEnum}) = ArrowTypes.PrimitiveKind
ArrowTypes.ArrowType(::Type{MyEnum}) = Int32

x = [LALA1, LALA1, LALA3, LALA2]
table = (cols1=x,)
io = IOBuffer()
Arrow.write(io, table)
seekstart(io)
table2 = Arrow.Table(io) # correctly reports 4 rows
table2.cols1

```

`ArrowTypes.ArrowType` seems to have been the missing piece, the above works returning:

```julia
4-element Arrow.Primitive{Main.AE.MyEnum, Vector{Int32}}:
 LALA1::MyEnum = 0
 LALA1::MyEnum = 0
 LALA3::MyEnum = 2
 LALA2::MyEnum = 1

```

---

<div class="post-metadata">

**Author:** ![digital\_carver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/digital_carver/32/33818_2.png) [@digital\_carver](https://discourse.julialang.org/u/digital_carver)\
**Post date:** [October 24, 2022, 1:41pm UTC](https://discourse.julialang.org/t/does-arrow-jl-support-enums/89163/9 "2022-10-24T13:41:36Z")

</div>

On the whole, the interface is not super intuitive. The docs don’t say what valid `ArrowTypes.ArrowType` values are, among other things. They mention "natively supported arrow type"s, but from the linked Apache Arrow [documentation](https://arrow.apache.org/docs/format/Columnar.html) it’s not easy to find what those are either.

They do say

> This stuff can definitely make your eyes glaze over if you stare at it long enough. As always, don’t hesitate to reach out for quick questions on the [#data](https://julialang.slack.com/messages/data/) slack channel, or [open a new issue](https://github.com/JuliaData/Arrow.jl/issues/new) detailing what you’re trying to do.

so it seems a good idea to actually open an issue to ask about the best way to serialize Julia Enums with Arrow (just in case the above is missing something), and to also ask for better clarification of this part of the documentation.

---

<div class="post-metadata">

**Author:** ![freeman](https://avatars.discourse-cdn.com/v4/letter/f/ec9cab/32.png) [@freeman](https://discourse.julialang.org/u/freeman)\
**Post date:** [October 25, 2022, 1:01am UTC](https://discourse.julialang.org/t/does-arrow-jl-support-enums/89163/10 "2022-10-25T01:01:28Z")

</div>

Thank you, this is exactly what I was looking for.

Yes, 100% agree. I found the docs are quite dense. And it’s surprising that such a simple case like enums isn’t an example, or even come implemented by default.

---

<div class="post-metadata">

**Author:** ![quinnj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/quinnj/32/11_2.png) [@quinnj](https://discourse.julialang.org/u/quinnj)\
**Post date:** [October 25, 2022, 6:16am UTC](https://discourse.julialang.org/t/does-arrow-jl-support-enums/89163/11 "2022-10-25T06:16:29Z")

</div>

Yeah, we could probably add default support for Enums, which would basically be the solution by @digital_carver, but for any `Enum` subtype. If someone is up for making a PR with a couple of tests, I’d appreciate it! Otherwise, if someone wants to open an issue, I can try to get to it soon.

---

<div class="post-metadata">

**Author:** ![Samuel\_H](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/samuel_h/32/220960_2.png) [@Samuel\_H](https://discourse.julialang.org/u/Samuel_H)\
**Post date:** [February 25, 2026, 9:36pm UTC](https://discourse.julialang.org/t/does-arrow-jl-support-enums/89163/12 "2026-02-25T21:36:59Z")

</div>

Hi,  
Allow me to continue this discussion.  
With Julia 1.12.5 and up-to-date package as of today

```julia
  [69666777] Arrow v2.8.1
  [31f734f8] ArrowTypes v2.3.0
  [a93c6f00] DataFrames v1.8.1

```

This following code crashes

```julia-auto
@enum OCPResult::Int8 begin
    Fee
    Foo
    Fuu
end
ArrowTypes.arrowname(::Type{OCPResult}) = :OCPResult
ArrowTypes.JuliaType(::Val{:OCPResult}) = OCPResult
ArrowTypes.ArrowKind(::Type{OCPResult}) = ArrowTypes.PrimitiveKind
ArrowTypes.ArrowType(::Type{OCPResult}) = Int8
ArrowTypes.toarrow(::Type{OCPResult}, x) = Int8(x)
ArrowTypes.fromarrow(::Type{OCPResult}, x) = OCPResult(x)
x=[Fee, Foo, Fuu]
table = (cols1=x,)
io = IOBuffer()
Arrow.write(io, table)
seekstart(io)
table2 = Arrow.Table(io) # correctly reports 4 rows
table2.cols1

```

The `write` fails with a conversion error.  
If I remove the `ArrowTypes.ArrowType()` call then the write work, but the conversion to a DataFrame fails (as is `DataFrame(Arrow.Table(...))`)  
I would appreciate help on both failures.  
Thank you!

---

<div class="post-metadata">

**Author:** ![Samuel\_H](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/samuel_h/32/220960_2.png) [@Samuel\_H](https://discourse.julialang.org/u/Samuel_H)\
**Post date:** [February 26, 2026, 7:42am UTC](https://discourse.julialang.org/t/does-arrow-jl-support-enums/89163/13 "2026-02-26T07:42:38Z")

</div>

Even simpler : the code suggested by @digital_carver does not compile anymore.

```julia-auto
 [69666777] Arrow v2.8.1
  [31f734f8] ArrowTypes v2.3.0
  [a93c6f00] DataFrames v1.8.1

```

```julia
julia> Arrow.write(io, table)
ERROR: TaskFailedException
Stacktrace:
 [1] #wait#582
   @ ./task.jl:363 [inlined]
 [2] wait
   @ ./task.jl:360 [inlined]
 [3] close(writer::Arrow.Writer{IOBuffer})
   @ Arrow ~/.julia/packages/Arrow/4zFuR/src/write.jl:353
 [4] open(::Arrow.var"#146#147"{@NamedTuple{cols1::Vector{MyEnum}}}, ::Type, ::Vararg{Any}; kwargs::@Kwargs{file::Bool})
   @ Base ./io.jl:412
 [5] open
   @ ./io.jl:407 [inlined]
 [6] #write#144
   @ ~/.julia/packages/Arrow/4zFuR/src/write.jl:406 [inlined]
 [7] write(io::IOBuffer, tbl::@NamedTuple{cols1::Vector{MyEnum}})
   @ Arrow ~/.julia/packages/Arrow/4zFuR/src/write.jl:405
 [8] top-level scope
   @ REPL[15]:1

    nested task error: MethodError: Cannot `convert` an object of type MyEnum to an object of type Int32
    The function `convert` exists, but no method is defined for this combination of argument types.
    
    Closest candidates are:
      (::Type{T})(::Enum{T2}) where {T<:Integer, T2<:Integer}
       @ Base Enums.jl:19
      convert(::Type{Int32}, ::Base.CoreLogging.LogLevel)
       @ Base logging/logging.jl:137
      convert(::Type{T}, ::Ptr) where T<:Integer
       @ Base pointer.jl:23
      ...
    
    Stacktrace:
     [1] _convert(::Type{Int32}, x::MyEnum)
       @ ArrowTypes ~/.julia/packages/ArrowTypes/IVpuP/src/ArrowTypes.jl:442
   [...]

```

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [March 5, 2026, 8:23pm UTC](https://discourse.julialang.org/t/does-arrow-jl-support-enums/89163/14 "2026-03-05T20:23:01Z")

</div>

I had Claude take a shot. I’m not familiar with the codebase but the code looks reasonable to me and the tests pass.

> <https://github.com/apache/arrow-julia/pull/588>
>
> \## Summary
> 
> \- Add serialization/deserialization support for Julia \`Enum\` types v…ia \`Int32\` storage
> \- Introduce \`registertype!\` for registering enum types in read-only scenarios (when the writing session is unavailable)
> \- Automatic type registration during writes via \`arrowmetadata\`
> \- Support for \`Union{Enum, Missing}\` columns
> 
> \## Test plan
> 
> \- \[x\] ArrowTypes unit tests: \`ArrowType\`, \`toarrow\`, \`arrowname\`, \`arrowmetadata\`, \`JuliaType\`, \`fromarrow\`, \`default\`, \`registertype!\`
> \- \[x\] Arrow integration tests: basic roundtrip, missing values, multiple enum columns, multiple record batches
> 
> 🤖 Generated with \[Claude Code\](https://claude.com/claude-code)
