Issue with dynamically generated values in array filter in Slack thread.
Looking at your GROQ query examples, the issue is about dynamic attribute access using variables with the @ operator (which refers to the current scope).
Here's what's happening:
Working examples:
"test": override_en_gb- Direct attribute access works"test1": @["override_en_gb"]- Bracket notation with a literal string works
Not working:
"test2": @["override_"+$lang]- String concatenation inside bracket notation doesn't work"test3": @[string("override_"+$lang)]- Even explicit string conversion doesn't work
The Problem
GROQ's bracket notation for attribute access (@[...]) expects a string literal or a direct variable reference, not a computed/concatenated expression. The expression inside the brackets is not evaluated as a dynamic key lookup in the way you might expect from JavaScript.
Solutions
Option 1: Use select() for conditional attribute access
*[]{
"test": select(
$lang == "en_gb" => @.override_en_gb,
$lang == "fr" => @.override_fr,
$lang == "de" => @.override_de
)
}This is the most GROQ-native approach - you explicitly handle each language case.
Option 2: Pre-compute the field name and use a parameter
If you're using a JavaScript client, compute the field name before passing it to GROQ:
const lang = "en_gb";
const fieldName = `override_${lang}`;
const query = `*[]{ "test": @[$fieldName] }`;
const result = await client.fetch(query, { fieldName });Option 3: Return the entire object and process client-side
*[]{ ... }Then in your application code:
const result = await client.fetch(query);
const processed = result.map(doc => ({
...doc,
test: doc[`override_${lang}`]
}));The fundamental limitation is that GROQ doesn't support dynamic string concatenation for property access paths. The bracket notation @[...] is meant for accessing properties with special characters or when the property name is stored in a variable, but that variable must contain the complete property name as a string value - not a concatenated expression.
If you need truly dynamic field access based on runtime values, Option 1 (select()) is your best bet for keeping the logic in GROQ, or Option 2/3 for handling it in your application code.
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.