The problem when you're using actual programs to generate JSON is that a single line:col in the original program is not enough to help you debug invalid output. The problem is harder than e.g. mapping ASM lines back to an original C program. Even a full stack trace is not enough because it does not track the data dependencies (i.e. through variables / parameters). So using JSONpath in errors is actually best because at least it gives you something that you can actually use to debug, no matter what the input.
What file line would you give for:
local func1(letter) = letter + 'ara'
local func2(letter) = letter + 'raph'
{
content: {
type: func1('t') + func2('g'),
}
and what would you give for:
local func1(letter) = letter + 'ora'
local func2(letter) = letter + 'raph'
{
content: {
type: func1('p') + func2('g'),
}
How would the system know the difference? And this is a relatively easy case where stack traces would be sufficient. What about:
local word = 'plate'
local index = 10 - 3 * 2 - 3;
local func1(letter) = letter + 'ara'
local func2(letter) = letter + 'raph'
{
content: {
type: func1(word[index]) + func2('g'),
}
You can see how this degenerates into the problem of "my 1 million line program produced 4 instead of 5, where is the bug?"
For me, an error message like "content.type was "laragraph" but expected "paragraph" is easy to implement and works well enough. If it's hard to get from that to the right place in your Jsonnet file, then probably the Jsonnet is too complicated or not modular enough (the above example is definitely "too complicated"!). If you're writing modular Jsonnet then test cases for those libraries help a lot to pick up the deep bugs and asserts can be used to check preconditions of functions / mixin fields. There has been previous discussion about some self.validateJsonSchema(value, schema) that could be used in asserts but the problem there was compatible implementations of JSON schema in different languages. Maybe that is no-longer an issue.