I have a PNG file that loads as an IndirectArray with an eltype of RGB{N0f8}:
I use the following code:
using FileIO
using ImageIO
function f()
img = load("mwe.png")
@show typeof(img)
return img[1]
end
Calling f() gives the following result:
typeof(img) = IndirectArrays.IndirectArray{ColorTypes.RGB{FixedPointNumbers.N0f8}, 2, UInt8, Matrix{UInt8}, OffsetArrays.OffsetVector{ColorTypes.RGB{FixedPointNumbers.N0f8}, Vector{ColorTypes.RGB{FixedPointNumbers.N0f8}}}}
CanonicalIndexError: getindex not defined for OffsetArrays.OffsetVector{ColorTypes.RGB{FixedPointNumbers.N0f8}, Vector{ColorTypes.RGB{FixedPointNumbers.N0f8}}}
Stacktrace:
[1] error_if_canonical_getindex(::IndexCartesian, A::OffsetArrays.OffsetVector{ColorTypes.RGB{FixedPointNumbers.N0f8}, Vector{ColorTypes.RGB{FixedPointNumbers.N0f8}}}, ::Int64)
@ Base .\abstractarray.jl:1357
[2] getindex
@ .\abstractarray.jl:1341 [inlined]
[3] _getindex
@ .\abstractarray.jl:1388 [inlined]
[4] getindex
@ .\abstractarray.jl:1342 [inlined]
[5] getindex(A::IndirectArrays.IndirectArray{ColorTypes.RGB{FixedPointNumbers.N0f8}, 2, UInt8, Matrix{UInt8}, OffsetArrays.OffsetVector{ColorTypes.RGB{FixedPointNumbers.N0f8}, Vector{ColorTypes.RGB{FixedPointNumbers.N0f8}}}}, i::Int64)
@ IndirectArrays ...\.julia\packages\IndirectArrays\BUQO3\src\IndirectArrays.jl:64
[6] f()
@ Main .\REPL[2]:4
[7] top-level scope
@ REPL[3]:1
A second call of the function gives the result I expected on the first call:
typeof(img) = IndirectArrays.IndirectArray{ColorTypes.RGB{FixedPointNumbers.N0f8}, 2, UInt8, Matrix{UInt8}, OffsetArrays.OffsetVector{ColorTypes.RGB{FixedPointNumbers.N0f8}, Vector{ColorTypes.RGB{FixedPointNumbers.N0f8}}}}
RGB{N0f8}(1.0, 1.0, 1.0)
Is there something I should be doing before the first getindex operation to ensure that it works?
It’s surely a world-age error. Try using IndirectArrays at the top of your file.
Thanks for the quick reply. Unfortunately, I get the same result.
Benny
March 3, 2026, 12:27am
4
Odd, I don’t get the error or the IndirectArray (Windows, Julia v1.12.5, FileIO v1.18.0, ImageIO v0.6.9, IndirectArrays v1.0.0):
julia> f()
typeof(img) = Matrix{ColorTypes.RGB{FixedPointNumbers.N0f8}}
RGB{N0f8}(1.0, 1.0, 1.0)
I right-click-saved the PNG image, maybe something was lost there?
That’s a package’s job, it’s abnormal for a first call to define a needed method.
I think the discourse software (or the browser) converts the format. I have put a copy of the original file here .
That’s a package’s job, it’s abnormal for a first call to define a needed method.
The package defines getindex(A::IndirectArray, i::Int), in a way that looks perfectly reasonable, but the error is thrown once control gets to Base.
Benny
March 3, 2026, 3:38am
6
I’m seeing the same error and array types now. Seeing something else weird:
julia> load("mwe.png") |> typeof
IndirectArrays.IndirectArray{ColorTypes.RGB{FixedPointNumbers.N0f8}, 2, UInt8, Matrix{UInt8}, OffsetArrays.OffsetVector{ColorTypes.RGB{FixedPointNumbers.N0f8}, Vector{ColorTypes.RGB{FixedPointNumbers.N0f8}}}}
julia> load("mwe.png") |> IndexStyle
IndexLinear()
julia> load("mwe.png").values |> typeof
OffsetVector{RGB{N0f8}, Vector{RGB{N0f8}}} (alias for OffsetArrays.OffsetArray{ColorTypes.RGB{FixedPointNumbers.Normed{UInt8, 8}}, 1, Array{ColorTypes.RGB{FixedPointNumbers.Normed{UInt8, 8}}, 1}})
julia> load("mwe.png").values |> IndexStyle
IndexLinear()
So where did that IndexCartesian come from? The last getindex just calls IndexStyle like the above:
function getindex(A::AbstractArray, I...)
@_propagate_inbounds_meta
error_if_canonical_getindex(IndexStyle(A), A, I...) # L1341
_getindex(IndexStyle(A), A, to_indices(A, I)...)
end
…and why does it suddenly work after the first call to getindex?
Still a world age error. But the missing packages turned out to be OffsetArrays and ColorVectorSpace.
The issue is that load loads packages on-demand, but this means new methods are getting defined while your compiled function f is running. Those are defined in a new world, but the compiled function is running in the old world. When you come back to the command-line prompt, the world age updates, so the next run works as expected.
Here’s how to diagnose what’s missing:
julia> using FileIO, ImageIO
julia> function f()
img = load("mwe.png")
@show typeof(img)
return img[1]
end
f (generic function with 1 method)
julia> mods = Base.loaded_modules_array();
julia> f()
typeof(img) = IndirectArrays.IndirectArray{ColorTypes.RGB{FixedPointNumbers.N0f8}, 2, UInt8, Matrix{UInt8}, OffsetArrays.OffsetVector{ColorTypes.RGB{FixedPointNumbers.N0f8}, Vector{ColorTypes.RGB{FixedPointNumbers.N0f8}}}}
ERROR: CanonicalIndexError: getindex not defined for OffsetArrays.OffsetVector{ColorTypes.RGB{FixedPointNumbers.N0f8}, Vector{ColorTypes.RGB{FixedPointNumbers.N0f8}}}
Stacktrace:
[1] error_if_canonical_getindex(::IndexCartesian, A::OffsetArrays.OffsetVector{ColorTypes.RGB{FixedPointNumbers.N0f8}, Vector{ColorTypes.RGB{FixedPointNumbers.N0f8}}}, ::Int64)
@ Base .\abstractarray.jl:1357
[2] getindex
@ .\abstractarray.jl:1341 [inlined]
[3] _getindex
@ .\abstractarray.jl:1388 [inlined]
[4] getindex
@ .\abstractarray.jl:1342 [inlined]
[5] getindex(A::IndirectArrays.IndirectArray{ColorTypes.RGB{FixedPointNumbers.N0f8}, 2, UInt8, Matrix{UInt8}, OffsetArrays.OffsetVector{ColorTypes.RGB{FixedPointNumbers.N0f8}, Vector{ColorTypes.RGB{FixedPointNumbers.N0f8}}}}, i::Int64)
@ IndirectArrays C:\Users\timho\.julia\packages\IndirectArrays\BUQO3\src\IndirectArrays.jl:64
[6] f()
@ Main .\REPL[4]:4
[7] top-level scope
@ REPL[6]:1
julia> mods2 = Base.loaded_modules_array();
julia> setdiff(mods2, mods)
20-element Vector{Module}:
Reexport
Statistics
FixedPointNumbers
ColorTypes
Colors
TensorCore
ColorVectorSpace
OffsetArrays
PaddedViews
MappedArrays
StackViews
MosaicViews
Preferences
PrecompileTools
ImageCore
JLLWrappers
libpng_jll
CEnum
PNGFiles
StyledStringsExt
But if you make sure that all the methods are defined before you run f for the first time (by pre-loading the required packages), then it works on first call.
load is convenient, but also a foot-gun for this reason.
4 Likes
tim.holy:
OffsetArrays
Thanks again for looking at this (thanks also to @Benny ). The minimum that will work in this case is
using FileIO, ImageIO, OffsetArrays
I will look into pre-load options. Is there an alternative to load? I would rather abandon convenience for reliability.
One option might be to add a noimports=true kwarg to load, and have it throw an error when it needs to load a package in order to satisfy the request. If you don’t want to implement that yourself, I would guess making that kind of change should be well within the capabilities of modern AI agents, so either way I encourage you to give it a try and submit a PR if it works.
2 Likes
Thanks for the feedback. I’ll take a look and see whether I can produce something that seems usable.