# Safe base64decode

**URL:** <https://discourse.julialang.org/t/safe-base64decode/91367>\
**Category:** General Usage\
**Tags:** question\
**Created:** [December 7, 2022, 2:47pm UTC](https://discourse.julialang.org/t/safe-base64decode/91367 "2022-12-07T14:47:52Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [December 7, 2022, 2:47pm UTC](https://discourse.julialang.org/t/safe-base64decode/91367/1 "2022-12-07T14:47:52Z")

</div>

I’d like to be able to `base64decode` a string without any risk of an `ArgumentError("malformed base64 sequence")` (see [here](https://github.com/JuliaLang/julia/blob/5060aedd56e2a2a6320b7fbe3b23541281901bb3/stdlib/Base64/src/decode.jl#L169)).

To that end, I can think of two main options:

1. Make a safe version of the `base64decode` function
2. Make a function that tests the validity of a string as a base64-encoded string

I know I can just wrap it with a try catch clause, but I’m trying to avoid that. I want to be able to safely decode the string or simply test its validity before decoding it.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [December 7, 2022, 3:16pm UTC](https://discourse.julialang.org/t/safe-base64decode/91367/2 "2022-12-07T15:16:06Z")

</div>

> [@yakir12](#):
>
> Make a safe version of the `base64decode` function

How is throwing an exception “unsafe”? What’s wrong with a `try` block?

That being said, a non allocating `Base64.isvalid` function seems like it could be a nice addition.

There is a StackOverflow answer giving [some regex solutions](https://stackoverflow.com/questions/475074/regex-to-parse-or-validate-base64-data). This seems like the easiest approach.

---

<div class="post-metadata">

**Author:** ![cjdoris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cjdoris/32/213133_2.png) [@cjdoris](https://discourse.julialang.org/u/cjdoris)\
**Post date:** [December 7, 2022, 4:42pm UTC](https://discourse.julialang.org/t/safe-base64decode/91367/3 "2022-12-07T16:42:37Z")

</div>

In analogy to `tryparse`, a `trybase64decode` function that returns `nothing` on invalid input would be good.

---

<div class="post-metadata">

**Author:** ![\_bernhard](https://avatars.discourse-cdn.com/v4/letter/_/bc79bd/32.png) [@\_bernhard](https://discourse.julialang.org/u/_bernhard)\
**Post date:** [December 7, 2022, 5:07pm UTC](https://discourse.julialang.org/t/safe-base64decode/91367/4 "2022-12-07T17:07:39Z")

</div>

Would the following work for you?

```julia
function trydecode(args...) 
    try
        decode(args...)
    catch e
        nothing
    end
end

```

---

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [December 7, 2022, 5:32pm UTC](https://discourse.julialang.org/t/safe-base64decode/91367/5 "2022-12-07T17:32:49Z")

</div>

> [@stevengj](#):
>
> How is throwing an exception “unsafe”? What’s wrong with a `try` block?

Nothing fundamentally wrong, or “unsafe”. But in code where failure is suboptimal (servers), I’d hope there would be a deterministic way to ascertain if something is base64-decodable. Perhaps there isn’t a way to answer that other than `try`ing to decode it and `catch`ing any eventual errors?

> [@stevengj](#):
>
> There is a StackOverflow answer giving [some regex solutions](https://stackoverflow.com/questions/475074/regex-to-parse-or-validate-base64-data)

Will this reasonably cover all the corner-cases? If so, then that is indeed easiest.

> [@cjdoris](#):
>
> In analogy to `tryparse`, a `trybase64decode` function that returns `nothing` on invalid input would be good.

This seems ideal to me.

> [@\_bernhard](#):
>
> Would the following work for you?

That is what I’m doing now, more or less.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [December 7, 2022, 7:16pm UTC](https://discourse.julialang.org/t/safe-base64decode/91367/6 "2022-12-07T19:16:32Z")

</div>

> [@cjdoris](#):
>
> In analogy to `tryparse`, a `trybase64decode` function that returns `nothing` on invalid input would be good.

I’m skeptical.

The reason for `tryparse`, in my view, is that parsing basic objects like `Float64` is a relatively cheap operation that often occurs in performance-critical inner loops, so the overhead of `try … catch` block is potentially significant.

In contrast, `base64` decoding is normally a relatively expensive operation done on large-ish blocks of binary data, so the overhead of a `try … catch` block should be negligible for typical usage.

Nor does `trybase64decode` avoid memory allocation for the result, which in my mind is the main reason for an `isvalidbase64` function.

---

<div class="post-metadata">

**Author:** ![cjdoris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cjdoris/32/213133_2.png) [@cjdoris](https://discourse.julialang.org/u/cjdoris)\
**Post date:** [December 7, 2022, 7:28pm UTC](https://discourse.julialang.org/t/safe-base64decode/91367/7 "2022-12-07T19:28:00Z")

</div>

s/would/could/ 🙂

The overhead of a try-catch block is small in the normal flow, but large when an exception does get thrown, though I forget how large… Maybe it’s still negligible compared to decoding.

---

<div class="post-metadata">

**Author:** ![yakir12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yakir12/32/297_2.png) [@yakir12](https://discourse.julialang.org/u/yakir12)\
**Post date:** [December 8, 2022, 8:43am UTC](https://discourse.julialang.org/t/safe-base64decode/91367/8 "2022-12-08T08:43:56Z")

</div>

Thank you all for the awesome feedback. I’ll sum this up since I feel this has come to a good conclusion:

There is no reason to create a validity check function that _probably_ covers 99.99% of the cases (@Aaron_Denney shared an excellent article about why one shouldn’t validate but parse instead: [Parse, don’t validate](https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/)). But there might be some value to a `trybase64decode` function with a return type of `Union{Nothing, Vector{Uint8}}`. The argument against that is that the added try-catch overhead is tiny compared to the time it takes to decode a string and therefore there is no point in investing in the development of this `trybase64decode` function.

As a side note, this highlights the difference between functions that succeed or throw an error and functions that succeed or return `nothing`. Is there some consensus on this programming-paradigm-question?

---

<div class="post-metadata">

**Author:** ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)\
**Post date:** [December 8, 2022, 12:48pm UTC](https://discourse.julialang.org/t/safe-base64decode/91367/9 "2022-12-08T12:48:13Z")

</div>

> [@yakir12](#):
>
> As a side note, this highlights the difference between functions that succeed or throw an error and functions that succeed or return `nothing`. Is there some consensus on this programming-paradigm-question?

BTW [Can we have result value convention for fast error handling? · JuliaLang/julia · Discussion #43773 · GitHub](https://github.com/JuliaLang/julia/discussions/43773) pushes for this paradigm (and also lists some [packages](https://github.com/JuliaLang/julia/discussions/43773#user-content-fn-results-869a19987cc126f4c1e3cbf9cff2cbc7) that help with working with that paradigm). Not sure there’s really consensus that it’s the right approach for Base though.
