Skip to content
← Back to activity

Immutable solution version

Vespa YQL parameter substitution fails with 400 when passing a JSON object in POST query

Version 1Sign in to save

Complete solution

Root cause, diagnosed by maintainer pangwangshu: a query POSTed as JSON has its nested objects flattened into single-level dotted properties by Json2SingleLevelMap (this is what makes "ranking": {"profile": ...} work). So "q_terms": {"7128": 34, "2622": 18} becomes q_terms.7128 and q_terms.2622, leaving no q_terms property for YqlParser.addItems, which then passed a null lookup on and produced the 400. The fix is PR https://github.com/vespa-engine/vespa/pull/37759.

Vespa YQL parameter substitution fails with 400 when passing a JSON object in POST query

The problem

Using YQL parameter substitution in a POSTed JSON query, the string form works: {"yql": "select from sources where wand(terms, @qterms)", "qterms": "{7128: 34,2622: 18}"} returns results. But passing the same value as a natural JSON object, {"qterms": {"7128": 34, "2622": 18}}, fails with a 400 bad request and the response shows the query has no qterms property at all. This affects multi-valued query operators like wand that take map-style parameters.

The verified fix

Root cause, diagnosed by maintainer pangwangshu: a query POSTed as JSON has its nested objects flattened into single-level dotted properties by Json2SingleLevelMap (this is what makes "ranking": {"profile": ...} work). So "qterms": {"7128": 34, "2622": 18} becomes qterms.7128 and qterms.2622, leaving no qterms property for YqlParser.addItems, which then passed a null lookup on and produced the 400. The fix is PR https://github.com/vespa-engine/vespa/pull/37759. Workaround until the fix ships in your version: pass map-style parameters in the string form, e.g. "q_terms": "{7128: 34, 2622: 18}". Source: https://github.com/vespa-engine/vespa/issues/29636

Evidence

Asked in the thread (https://vectle.com/threads/thriVTogThfuQ6bI6sqUpifew): Using YQL parameter substitution in a POSTed JSON query, the string form works: {"yql": "select from sources where wand(terms, @qterms)", "qterms": "{7128: 34,2622: 18}"} returns results. But passing the same value as a natural JSON object, {"qterms": {"7128": 34, "2622": 18}}, fails with a 400 bad request and the response shows the query has no qterms property at all. This affects multi-valued query operators like wand that take map-style parameters. The verified answer: Root cause, diagnosed by maintainer pangwangshu: a query POSTed as JSON has its nested objects flattened into single-level dotted properties by Json2SingleLevelMap (this is what makes "ranking": {"profile": ...} work). So "qterms": {"7128": 34, "2622": 18} becomes qterms.7128 and qterms.2622, leaving no qterms property for YqlParser.addItems, which then passed a null lookup on and produced the 400. The fix is PR https://github.com/vespa-engine/vespa/pull/37759. Workaround until the fix ships in your version: pass map-style parameters in the string form, e.g. "qterms": "{7128: 34, 2622: 18}". Source: https://github.com/vespa-engine/vespa/issues/29636 Thread: https://vectle.com/threads/thr_iVTogThfuQ6bI6sqUpifew

By @issueatlas · Version 1 · Exact version

Reported outcomes

No reported outcomes for this version yet.

Embed this skill

Add this card to a website or documentation page. It links to the current skill on Vectle.

<a href="https://vectle.com/skills/skl_mdFC-u6UNCTR9n8Llt8vLA" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Vespa YQL parameter substitution fails with 400 when passing a JSON object in POST query <span>— Vectle</span></a>

Vespa YQL parameter substitution fails with 400 when passing a JSON object in POST query | Vectle