# \`add\_artifact!\` fails because of a checksum test, while the tarball was made with \`Tar.jl\`

**URL:** https://discourse.julialang.org/t/add-artifact-fails-because-of-a-checksum-test-while-the-tarball-was-made-with-tar-jl/87306
**Category:** General Usage
**Tags:** question, artifacts
**Created:** [September 15, 2022, 9:42am UTC](https://discourse.julialang.org/t/add-artifact-fails-because-of-a-checksum-test-while-the-tarball-was-made-with-tar-jl/87306 "2022-09-15T09:42:21Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![BambOoxX](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bambooxx/32/22179_2.png) [@BambOoxX](https://discourse.julialang.org/u/BambOoxX)
#### Post date: [September 15, 2022, 9:42am UTC](https://discourse.julialang.org/t/add-artifact-fails-because-of-a-checksum-test-while-the-tarball-was-made-with-tar-jl/87306/1 "2022-09-15T09:42:21Z")

</div>

Hello, I’m trying to add some binary artifacts to one of my packages.  
As I am on windows, I do not use `BinaryBuilder` as it does not seem supported at the moment for that OS. However, I tried using `ArtifactUtils` to ease up the process.

Here are the steps I followed :

1. I created a tarball of the folder that I want to use as an artifact with

```julia
Tar.create("<path to folder>","<myartifactname>.tar.gz")

```

1. I sent it in a shared folder on a NAS server in my private network

```julia
cp("<myartifactname>.tar.gz","<myartifact path>.tar.gz")

```

1. I attempted to add the artifact to my package, here is where it fails for now

```julia
using ArtifactUtils, Pkg.Artifacts, Base.BinaryPlatforms

add_artifact!(
    "Artifacts.toml",
    "<myartifactname>",
    "file::////<myartifact path>.tar.gz", # becasuse `add_artifact` wants URLs
    platform = Platform("x86_64","windows")
)

```

At that point I receive several errors

> ERRORS:  
> Unexpected end of archive  
> ERROR: The communication channel is about to be closed (in the system regional language)  
> ERROR: This does not appear to be a TAR file/stream — malformed chksum field: “\xb9\x01\xc1\xf8\xa3j\xc4\xf9”. Note: Tar.jl does not handle decompression; if the tarball is compressed you must use an external command like `gzcat` or package like CodecZlib.jl to decompress it. See the README file for examples.

However, the tarball involved here was created using `Tar.jl`, and I can `extract` it without errors with `Tar` or with an external tool.

What I can’t figure is why does `add_artifact` complain about the tarball, while `Tar` itself does not. It may be straightforward for experienced Artifact users, but it’s my first time attempting that or working with tarballs.

The stacktrace is the following

> Stacktrace:  
> [1] error(s::String)  
> @ Base .\error.jl:35  
> [2] |\>(x::String, f::typeof(error))  
> @ Base .\operators.jl:911  
> [3] header\_error(buf::Vector{UInt8}, msg::String)  
> @ Tar Julia-1.8.0\share\julia\stdlib\v1.8\Tar\src\extract.jl:555  
> [4] header\_error(buf::Vector{UInt8}, fld::Symbol)  
> @ Tar Julia-1.8.0\share\julia\stdlib\v1.8\Tar\src\extract.jl:567  
> [5] read\_header\_int(buf::Vector{UInt8}, fld::Symbol)  
> @ Tar Julia-1.8.0\share\julia\stdlib\v1.8\Tar\src\extract.jl:658  
> [6] check\_checksum\_field(buf::Vector{UInt8})  
> @ Tar Julia-1.8.0\share\julia\stdlib\v1.8\Tar\src\extract.jl:618  
> [7] read\_standard\_header(io::Base.Process; buf::Vector{UInt8}, tee::Base.DevNull)  
> @ Tar Julia-1.8.0\share\julia\stdlib\v1.8\Tar\src\extract.jl:587  
> [8] #read\_header#50  
> @ Julia-1.8.0\share\julia\stdlib\v1.8\Tar\src\extract.jl:415 [inlined]  
> [9] read\_tarball(callback::Tar.var"#26#28"{Vector{UInt8}, Bool, Bool, Base.Process, String}, predicate::Tar.var"#1#2", tar::Base.Process; buf::Vector{UInt8}, skeleton::Base.DevNull)  
> @ Tar Julia-1.8.0\share\julia\stdlib\v1.8\Tar\src\extract.jl:345  
> [10] extract\_tarball(predicate::Function, tar::Base.Process, root::String; buf::Vector{UInt8}, skeleton::Base.DevNull, copy\_symlinks::Bool, set\_permissions::Bool)  
> @ Tar Julia-1.8.0\share\julia\stdlib\v1.8\Tar\src\extract.jl:58  
> [11] (::Tar.var"#85#88"{String, Base.Process, Bool, Tar.var"#1#2"})(skeleton::Base.DevNull)  
> @ Tar Julia-1.8.0\share\julia\stdlib\v1.8\Tar\src\Tar.jl:237  
> [12] arg\_write(f::Tar.var"#85#88"{String, Base.Process, Bool, Tar.var"#1#2"}, arg::Base.DevNull)  
> @ ArgTools Julia-1.8.0\share\julia\stdlib\v1.8\ArgTools\src\ArgTools.jl:134  
> [13] #84  
> @ Julia-1.8.0\share\julia\stdlib\v1.8\Tar\src\Tar.jl:236 [inlined]  
> [14] arg\_mkdir(f::Tar.var"#84#87"{Base.Process, Base.DevNull, Bool, Tar.var"#1#2"}, arg::String)  
> @ ArgTools Julia-1.8.0\share\julia\stdlib\v1.8\ArgTools\src\ArgTools.jl:185  
> [15] #83  
> @ Julia-1.8.0\share\julia\stdlib\v1.8\Tar\src\Tar.jl:232 [inlined]  
> [16] open(::Tar.var"#83#86"{Base.DevNull, Bool, Tar.var"#1#2", String}, ::Cmd; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})  
> @ Base .\process.jl:427  
> [17] open(::Function, ::Cmd)  
> @ Base .\process.jl:414  
> [18] arg\_read  
> @ Julia-1.8.0\share\julia\stdlib\v1.8\ArgTools\src\ArgTools.jl:75 [inlined]  
> [19] extract(predicate::Function, tarball::Cmd, dir::String; skeleton::Nothing, copy\_symlinks::Nothing, set\_permissions::Bool)  
> @ Tar Julia-1.8.0\share\julia\stdlib\v1.8\Tar\src\Tar.jl:231  
> [20] #extract#89  
> @ Julia-1.8.0\share\julia\stdlib\v1.8\Tar\src\Tar.jl:255 [inlined]  
> [21] unpack(tarball\_path::String, dest::String; verbose::Bool)  
> @ Pkg.PlatformEngines Julia-1.8.0\share\julia\stdlib\v1.8\Pkg\src\PlatformEngines.jl:389  
> [22] unpack  
> @ Julia-1.8.0\share\julia\stdlib\v1.8\Pkg\src\PlatformEngines.jl:384 [inlined]  
> [23] #25  
> @ .julia\packages\ArtifactUtils\vpjlQ\src\ArtifactUtils.jl:66 [inlined]  
> [24] create\_artifact(f::ArtifactUtils.var"#25#26"{String})  
> @ Pkg.Artifacts Julia-1.8.0\share\julia\stdlib\v1.8\Pkg\src\Artifacts.jl:45  
> [25] add\_artifact!(artifacts\_toml::String, name::String, tarball\_url::String; clear::Bool, options::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})  
> @ ArtifactUtils .julia\packages\ArtifactUtils\vpjlQ\src\ArtifactUtils.jl:65  
> [26] add\_artifact!(artifacts\_toml::String, name::String, tarball\_url::String)  
> @ ArtifactUtils .julia\packages\ArtifactUtils\vpjlQ\src\ArtifactUtils.jl:52

---

<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: [September 15, 2022, 5:20pm UTC](https://discourse.julialang.org/t/add-artifact-fails-because-of-a-checksum-test-while-the-tarball-was-made-with-tar-jl/87306/2 "2022-09-15T17:20:00Z")

</div>

> [@BambOoxX](#):
>
> `Tar.create("<path to folder>","<myartifactname>.tar.gz")`

If you look at the [Compression](https://github.com/JuliaIO/Tar.jl#compression) section of the Tar.jl Readme:

> It is typical to compress tarballs when saving or transferring them. In the UNIX tradition of doing one thing and doing it well, the `Tar` package does not do any kind of compression and instead makes it easy to compose its API with external compression tools.

Translation: when you call `Tar.create` above, you’re actually creating just a `.tar` file, even though you’ve given it a `.tar.gz` extension. The Readme then goes on to give suggestions about how to create a _compressed_ tarball.

You can adapt the “Creating a tarball with the `gzip` command” code, to use whichever compression tool you have available on Windows.  
Or you can use the TranscodingStreams based idea suggested after that.

> [@BambOoxX](#):
>
> What I can’t figure is why does `add_artifact` complain about the tarball, while `Tar` itself does not.

The difference is that `Tar.extract` expects a `.tar` file i.e. a basic tarball, whereas `add_artifact!` expects a _compressed_ tarball (even though its documentation doesn’t clearly say this and should be updated).

---

<div class="post-metadata">

### Author: ![BambOoxX](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bambooxx/32/22179_2.png) [@BambOoxX](https://discourse.julialang.org/u/BambOoxX)
#### Post date: [September 16, 2022, 8:41am UTC](https://discourse.julialang.org/t/add-artifact-fails-because-of-a-checksum-test-while-the-tarball-was-made-with-tar-jl/87306/4 "2022-09-16T08:41:31Z")

</div>

The really important part is indeed that

> [@digital\_carver](#):
>
> The difference is that `Tar.extract` expects a `.tar` file i.e. a basic tarball, whereas `add_artifact!` expects a _compressed_ tarball (even though its documentation doesn’t clearly say this and should be updated).
