While I was reviewed a patch with "json_insert" function I found a bug which wasn't connected with the patch and reproduced at master.
It claims about non-integer whereas input values are obvious integers and in an allowed range. More testing lead to understanding it appears when numbers length are multiplier of 4:
postgres=# select jsonb_set('{"a":[[],1,2,3],"b":[]}', '{"a", 9999}', '"4"'); ERROR: path element at the position 2 is not an integer
Hmm, I see in master
select version(); version ----------------------------------------------------------------------------------------------------------------- PostgreSQL 9.6devel on x86_64-apple-darwin15.4.0, compiled by Apple LLVM version 7.3.0 (clang-703.0.29), 64-bit (1 row)
Research lead to setPathArray where a string which is got via VARDATA_ANY but is passed to strtol which expects cstring.
In case of string number length is not a multiplier of 4 rest bytes are padding by '\0', when length is a multiplier of 4 there is no padding, just garbage after the last digit of the value.
Proposed patch in an attachment fixes it.
There is a magic number "20" as a length of an array for copying key from a path before passing it to strtol. It is a maximal length of a value which can be parsed by the function. I could not find a proper constant for it. Also I found similar direct value in the code (e.g. in numeric.c).