cue icon indicating copy to clipboard operation
cue copied to clipboard

confusing error message when a definition uses a required field in a dynamic field expression

Open sergio91pt opened this issue 1 month ago • 4 comments

What version of CUE are you using (cue version)?

$ cue version

cue version v0.15.1

CUE language version v0.15.1

Go version go1.25.4
      -buildmode exe
       -compiler gc
       -trimpath true
     CGO_ENABLED 0
          GOARCH arm64
            GOOS darwin
         GOARM64 v8.0

Does this issue reproduce with the latest stable release?

Yes, it reproduces starting from v0.15.0-alpha3. It is working correctly on v0.14.2

What did you do?

package test

#Manifest: {
	apiVersion!: "v1"
	kind!:       "__kind"
}

#GeneratorInput: {
	(#Manifest.kind): {
		(#Manifest.apiVersion): #Manifest
	}
}

_input: #GeneratorInput
_input: "__kind": "v1": {
	apiVersion: "v1"
	kind:       "__kind"
}

output: _input[#Manifest.kind][#Manifest.apiVersion]

What did you expect to see?

Running a cue export for this snippet should output:

{
    "output": {
        "apiVersion": "v1",
        "kind": "__kind"
    }
}

What did you see instead?

_input."__kind": field not allowed:
    ./test.cue:15:9

Removing the required markers ! from apiVersion and kind makes it work again.

sergio91pt avatar Nov 22 '25 14:11 sergio91pt

Bisected this issue to commit a25fb94136c3c3e530a0341715e31d8ccd21ba8a

sergio91pt avatar Nov 22 '25 15:11 sergio91pt

Reduced to the following testscript:

exec cue export in.cue

-- in.cue --
#Object: version!: "v1"

#Output: (#Object.version): #Object

out: #Output
out: v1: version: "v1"

Below are the results with v0.14.2 and master (166a851f1f6337adefd484aff8643f31c9f3b836):

> exec cue-v0.14.2 export in.cue
[stdout]
{
    "out": {
        "v1": {
            "version": "v1"
        }
    }
}
> exec cue export in.cue
[stderr]
out.v1: field not allowed:
    ./in.cue:6:6

I also bisected this to a25fb94136c3c3e530a0341715e31d8ccd21ba8a.

I believe this is working as intended; in my reduced example, the selection of #Object.version is an error, because you're accessing a required field that isn't present. As such, #Output ends up not allowing any fields. Perhaps the error here is confusing; it could error at the declaration of #Output, which might be more helpful, but I don't think it should work given the current CUE language spec.

I see a few possible solutions here:

  1. Declare the string you need to reuse separately, outside of a required field. This is what I would do, as reusing a value from a required field is not a very good setup right now.
  2. When selecting the required field, "fill it" as a regular field so that you can get its value. For example, in my reduction: #Output: ((#Object & {version: _}).version): #Object

mvdan avatar Nov 22 '25 15:11 mvdan

In other words, the commit that we bisected is a bugfix; older versions of CUE did not correctly apply the required field semantics outlined in the language spec.

mvdan avatar Nov 22 '25 15:11 mvdan

With @cuematthew we're in agreement that this should indeed fail, and that commit was a bugfix, but that the error you're seeing now is not ideal. I'll repurpose this issue to track the less-than-ideal error.

That is, the testscript in https://github.com/cue-lang/cue/issues/4192#issuecomment-3566805582 should fail with a message like the one I get if I make #Output a non-definition like Output:

Output: key value of dynamic field must be concrete, found _|_(Output: required field missing: version):

mvdan avatar Nov 25 '25 14:11 mvdan