Helm: --set parses number only values as float64

Created on 17 Dec 2016  ·  68Comments  ·  Source: helm/helm

I just noticed that something like helm install --set tag=20161216 ends up in scientific notation in the template and thats because {{ typeOf .Value.tag }} yields float64.

Thats even true for small integers like helm install --set tag=1 --> float64.

This is happening with helm 2.1.0

help wanted

Most helpful comment

Backwards compatibility? Of a feature that is just plain 'WTF' and likely not many want or use it? In a tool that's under heavy development and not really adopted broadly? I suggest to rethink that and fix it before it's really late.

All 68 comments

Does it work differently if you do --set tag=\"1\"?

Thanks to @chancez we know the exact problem: During the conversions to and from JSON done by ghodss/yaml, integers are being cast into float64s to represent Javascript's numeric type. This is causing all integers above a certain value to be represented in scientific notation.

I've been bitten by the same problem. The way of getting over the hump (or the bug) is to do this:

--set bignumber=\\"a185576882739235744\\"

Another workaround we have used is to do stuff like this:

--set port=":1234567"

Then in the template:

{{ .Values.port | replace ":" "" }}

Yuck! 😷

This is a heck of a pain, and @ipedrazas' workaround doesn't seem to work for me, or any other combination of quoting/escaping I've tried.

I'm not quite willing yet to swallow my pride and try @technosophos' ugly hack...

For now I'm hacking around this by expanding my deploy script to write the data as yaml to a temporary file and use that as a -f argument.

I'm facing the same issue from time to time for the image tag.
I'll try to use one of these workaround. I hope it will be fixed soon :)

In my case, seeing this below on --set image.tag=5997578:

$ kubetctl describe po msj-treasure-map-msj-treasure-map-192172122-dnb80
...
Events:
  Type     Reason         Age               From                                    Message
  ----     ------         ----              ----                                    -------
  Normal   Scheduled      1m                default-scheduler                       Successfully assigned msj-treasure-map-msj-treasure-map-192172122-dnb80 to ip-10-253-13-113.ec2.internal
  Warning  InspectFailed  15s (x9 over 1m)  kubelet, ip-10-253-13-113.ec2.internal  Failed to apply default image tag "596297932419.dkr.ecr.us-east-1.amazonaws.com/msj-trmap-uwsgi:5.997578e+06": couldn't parse image reference "596297932419.dkr.ecr.us-east-1.amazonaws.com/msj-trmap-uwsgi:5.997578e+06": invalid reference format
  Warning  InspectFailed  15s (x9 over 1m)  kubelet, ip-10-253-13-113.ec2.internal  Failed to apply default image tag "596297932419.dkr.ecr.us-east-1.amazonaws.com/msj-trmap-nginx:5.997578e+06": couldn't parse image reference "596297932419.dkr.ecr.us-east-1.amazonaws.com/msj-trmap-nginx:5.997578e+06": invalid reference format
  Warning  FailedSync     15s (x9 over 1m)  kubelet, ip-10-253-13-113.ec2.internal  Error syncing pod, skipping: [failed to "StartContainer" for "msj-treasure-map-uwsgi" with InvalidImageName: "Failed to apply default image tag \"596297932419.dkr.ecr.us-east-1.amazonaws.com/msj-trmap-uwsgi:5.997578e+06\": couldn't parse image reference \"596297932419.dkr.ecr.us-east-1.amazonaws.com/msj-trmap-uwsgi:5.997578e+06\": invalid reference format"
, failed to "StartContainer" for "msj-treasure-map-nginx" with InvalidImageName: "Failed to apply default image tag \"596297932419.dkr.ecr.us-east-1.amazonaws.com/msj-trmap-nginx:5.997578e+06\": couldn't parse image reference \"596297932419.dkr.ecr.us-east-1.amazonaws.com/msj-trmap-nginx:5.997578e+06\": invalid reference format"
$ helm version                                                                                                                                                                             
Client: &version.Version{SemVer:"v2.5.1", GitCommit:"7cf31e8d9a026287041bae077b09165be247ae66", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.5.1", GitCommit:"7cf31e8d9a026287041bae077b09165be247ae66", GitTreeState:"clean"}

I am also experiencing the same problem on helm 2.6.2.

Client: &version.Version{SemVer:"v2.6.2", GitCommit:"be3ae4ea91b2960be98c07e8f73754e67e87963c", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.6.2", GitCommit:"be3ae4ea91b2960be98c07e8f73754e67e87963c", GitTreeState:"clean"}
  • 1

Stripping YAML down to JSON removes a lot of information, most type related. Means you can't type check values pre-deploy.

I guess this can be resolved by moving to a different yaml library. Maybe this one: https://github.com/go-yaml

While struggling with this issue today I found out that the toString filter can help with this:

dockerPort: {{ .Values.dockerPort | toString }}

Then I was able to pass the port in command line (--set dockerPort=2376) and have it interpreted correctly.

We just saw this on 2.7.2 and most of the workarounds don't really work for us except writing all the --set options to a local file and passing that via helm -f locals.yml.

I have also seen this in 2.7.2 (and filed #3246 as a result), so +1 on this issue. Like in https://github.com/kubernetes/helm/issues/3001, I was also using the git SHAs for my docker image tags. My workaround for now, FWIW, is to suffix image tags with -gitsha

+1 for me as well.

$ helm version                                                                                                                                    ⏎
Client: &version.Version{SemVer:"v2.7.2", GitCommit:"8478fb4fc723885b155c924d1c8c410b7a9444e6", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.7.2", GitCommit:"8478fb4fc723885b155c924d1c8c410b7a9444e6", GitTreeState:"clean"}

$ git rev-parse --short HEAD
6180689

$ helm upgrade foobar \
    -i charts/foobar \
    --set image.tag=$(git rev-parse --short HEAD) \
    --reuse-values

After deploy, I get this:

Failed to apply default image tag "gcr.io/foobar/foobar:6.180689e+06": couldn't parse image reference "gcr.io/foobar/foobar:6.180689e+06": invalid reference format
Error syncing pod

I also get InvalidImageName upon running kubectl get pods.

Appending | toString does not appear to make a difference for me.

can you just do:

{{ .Values.tag | int64 }}

@laverite in charts absolutely, but this is using the --set parser. This problem only exists for the --set parser. values passed in via values.yaml are parsed correctly. :)

It appears this is related to #3155

yep, believe so @jesselang

Same problem here with helm 2.8.0.

@bacongobbler or @technosophos I have a fix for this issue on #3599 , there's already one approval, just need another. Thanks!

resolved via #3599

thanks for the ping @arturo-c :)

Seeing this bug too with Helm 2.9.1

I wonder why helm lint doesn't catch this? See #4099

I'm curious why this was solved by adding --set-string, instead of fixing what seems to me to be an obvious bug in --set.

Is it likely that anyone is intending numbers to get coerced to scientific notation in their yaml files?

two words: Backwards compatibility :)

We can change how the --set parser coerces integer values in Helm 3, but generally speaking we've opted to prevent changing the expected behaviour of core functionality like --set since there are so many users running Helm in production. We can't also coerce all values in --set to strings since that'll break existing behaviour such as the expected behaviour around null and truthy values in values files, so --set-string was accepted as a workable solution for the time being.

Backwards compatibility? Of a feature that is just plain 'WTF' and likely not many want or use it? In a tool that's under heavy development and not really adopted broadly? I suggest to rethink that and fix it before it's really late.

@technosophos thanks.
Example:

kind: Secret
data:
  some_db_port: {{ .Values.dbInfo.db_port | replace ":" "" | b64enc }}

it's work for me.

@OndraZizka thank you for the (very passionate) feedback. We're definitely looking into addressing some of these wonky behavioral issues that the --set parser has for Helm 3, likely by replacing it with something similar to the new --set-string parser.

I fully agree that the behavior of --set is very odd in this case (and even downright wrong), but we can't expect to replace an entire parsing library with another and be confident that there to be no other coercion bugs in the new system. Swapping coercion libraries would be considered a backwards-incompatible change.

For the time being, --set-string is a great feature and I highly recommend it to anyone else running into this bug to please use --set-string as much as possible when you don't rely on type coercion. That way, values are forced to be coerced as a string, and not as a float.

Unfortunately, when Ansible formats a dict to yaml (which is my values.yaml), it doesn't add any quotes, which is a big issue for me. I can't believe I have to use this bloody hack: replace ":" ""

if you need a work around that works without prefixing the tag with a : and removing it later, you can use this one (tl;dr: when tag is a number, use printf to print it, otherwise print the string you got)

{{- $tag :=  .Values.image.tag }}
{{- $type := printf "%T" $tag }}
image: "{{ .Values.image.repository }}:{{if eq $type "float64"}}{{ printf "%.0f" $tag }}{{ else }}{{ $tag }}{{ end }}"

The bug also happens with helm ... -f myval.yaml

@bacongobbler still happening on me with helm version v2.14.3

Can you open a new issue? Thanks.

re-opening because of the need to revert #6010 in #6749.

Any ETA when the fix would be available?

see #6888.

@sagarkal to make sure we're on the same page: the aforementioned fix is only aiming to reach up Helm v3, not v2 (I'm declaring this as a random contributor, the actual decision is always up to the team). The change is relatively massive and shouldn't be considered 100% safe to get merged into 2.x branch, which is patch-only now. In the meantime, if you have a chance, it would be great if you could test the PR branch against your use case and let us know if things work as expected. That would help a lot!

Using --set-string image.tag=6599236 worked for me with a plain template like this

  ...
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          env:
  ...

Running into this with a large integer value specified in the chart's values file. It is implicitly converted to a float with scientific notation. Just casting the value to an int fixed this, and seems much cleaner than some of the other workarounds I've seen:

# values.yaml

tomcat:
  maxPostSize: 2097152
# Cast to int when used

{{ .Values.tomcat.maxPostSize | int }}

This was tested with Helm v3.1.1.

That is good to know! That is definitely an easy workaround compared to many of the ones I have seen. Thanks!

@Rathgore Casting to an int is perfect when dealing with ints all of the time but in my case the input value needs to be treated as a string but comes in the form of digits (sometimes). For example the shortened 7 length github commit hash, sometimes it's a string and sometimes it's just a string of digits. In this case passing in the value with the --set-string option works every time.

@m0rganic I haven't tested this, but you could try using toString instead of int or explicitly setting the type using !!str. This isn't needed if you're just using --set-string but we need this behavior for values defined in the chart as well.

@m0rganic I haven't tested this, but you could try using toString instead of int or explicitly setting the type using !!str. This isn't needed if you're just using --set-string but we need this behavior for values defined in the chart as well.

toString doesn't work, and in some cases, I couldn't use !!str.

Is there a plan to fix this behavior? This issue has been open for quite a while...

See #6888. Otherwise, no. We've documented many patterns to use. But we haven't found a solution that solves more issues than it causes. Feel free to try your hand at a PR.

Thanks for the quick response! I'm not certain that any of the proposed workarounds solve my usecase but I'll try again.

Does it work differently if you do --set tag=\"1\"?

in my case I used "" in the int, float and bool values and it worked, thanks

Based on this comment, it may appear this is no longer an issue for Helm 3, just for Helm 2. I'd love to hear who is still running into this issue, how, and with what versions of Helm.

For Helm 2 users, we are only accepting security patches at this point, so we will not be looking to fix this bug for Helm 2. However, if this is still relevant for Helm 3, I'd appreciate more information from the community on this particular bug.

for helm 2 you may cast to whatever you want between the ( ) as the example below

{{- range $i := until (int .Values.deployment.numberofracks) }}
  - name: rack{{$i}}
{{- end}}

I'm going to assume this has been fixed for Helm 3, as it's been 3 weeks since I last posted that this appears to have been fixed. If there are still others experiencing this issue with Helm 3, please feel free to discuss this and we can re-open this issue. Thanks!

This is still an issue; I'm on 3.3.0 and still experiencing this.

Can you please provide a demonstration?

Happy to, but I'm not fully sure how to do that; I have a Chart which has in its values.yaml a field which looks like this:

customEnv:
  SOME_ENV_VAR: 10000000

and then in templates/deployment.yaml, I have this:

    ...
    containers:
      - name: someContainer
        env:
           {{- range $key, $value := .Values.customEnv }}
            - name: {{ $key | quote }}
              value: {{ $value | quote }}
          {{- end }}
    ...

When I run helm template, I get this value in the rendered output:

    ...
    containers:
      - name: someContainer
        env:
            - name: "SOME_ENV"
              value: "1e+07"
   ...

and then my deployed application fails when it tries to parse the value of SOME_ENV as a number.

Okay. I managed to reproduce the same issue following your instructions with Helm 3.3.1. Thank you. Re-opening.

I'm hitting the same issue for a slightly different angle. My appVersion is 8482e77, if I reference appVersion anywhere it gets rendered as +Inf. This is fun to debug BTW.

Edit:
changing appVersion from appVersion: 8482e77 to appVersion: "8482e77" fixed my issue

That’s to be expected. Unquoted, YAML parses that value as scientific notation (as 8482e77 means “8482 * 10^77”). If you want a value to be treated as a string, wrap it in quotes.

I had this issue with contianer image tag. The problem were addressed creating the helper below:

+{{/* Generate Image Name */}}
+{{- define "helpers.image" }}
+{{- $tag := printf "%f" .Values.app.image.tag -}} 
+{{- if regexMatch "^[0-9]+\\.[0-9]+$" $tag }}
+{{ .Values.image.repository }}:{{ .Values.image.tag | int }}
+{{- else }}
+{{ .Values.image.repository }}:{{ .Values.image.tag }}
+{{- end }}
+{{- end }}

And then, at Deployment manifest:

   containers:
       - name: {{ template "helpers.fullname" . }}
         image: {{ template "helpers.image" . }}

is this issue fixed ? if not, then I would like to fix this.

No. See above. Please make sure to read the thread and test for yourself. :)

This issue has been marked as stale because it has been open for 90 days with no activity. This thread will be automatically closed in 30 days if no further activity occurs.

bump, still an issue

I am using this workaround when I meet this problem on maybe-numeric commit ids:

{{- define "numericSafe" -}}
{{- if . | toString | contains "e+" -}}
{{ . | toString | replace "." "" | regexFind "^\\d+" }}
{{- else -}}
{{ . }}
{{- end -}}
{{- end -}}

then use with

{{ include "numericSafe" .Values.git.commitID }}

It solves problems if your original string never contains dot and e+, though I don't know if it's a very long number string anything will be omitted.

@urakagi unfortunately, that doesn't work if your value is: 1800000

Is there a fix planned for this issue?

Any updates?

@bacongobbler the repro from @edobry is actually a different issue. This one was originally about values being passed in with --set, which has now been fixed and the --set-string option was added.

The repro is about a number inside values.yaml being changed into scientific notation. The repro can be fixed with quoting the number in values.yaml, if it should be treated as a string. If it is used as a number, the notations shouldn't be an issue.

I looked into the code and I think I would be able to change the behaviour to output numbers in standard notation instead up to 20 decimal digits numbers. After that there seem to be some implementation limit in the underlying yaml parser that rounds very large numbers and/or turns them into scientific notation.

I have also tried to find another issue that would deal with the issue as described in @edobry 's repro and I have found #9162 where the resolution seems to be that this is intended as the parser parses the values as it sees fit and within the bounds of the yaml specification.

So when someone uses e.g. numerical tags, which don't have any numerical values (no arithmetic is defined on them), they should be quoted in values.yaml to be treated as strings and that should fix the issue:

# values.yaml
foo: "10000000"
# template
foo: {{ .Values.foo | quote }}



md5-aba98a385ca8fe457cb1f98967ed3bf1



# Source: foo/templates/x.yaml
foo: "10000000"



md5-265ed31678f08bdbd76c259b974f5398



# Source: foo/templates/x.yaml
foo: "1e+07"



md5-3df6a1bc5fe8f474ded5c2033aaf11a3



# Source: foo/templates/x.yaml
foo: "10000000"

Therefore I think this can be closed and a new issue can be open if someone thinks that the parsing of unquoted numbers should follow some other rules than it already does.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

macknight picture macknight  ·  3Comments

InAnimaTe picture InAnimaTe  ·  3Comments

adam-sandor picture adam-sandor  ·  3Comments

naveensrinivasan picture naveensrinivasan  ·  3Comments

dkirrane picture dkirrane  ·  3Comments