Summary
kbagent config new --push has no way to duplicate an existing configuration, so cloning one has to be done by hand-reconstructing the configuration body from config detail output. It's very easy to silently drop a sibling top-level key this way — in our case runtime (specifically runtime.parallelism) — because nothing in config new, config examples, or the docs calls out that a component's root config can have siblings of parameters (runtime, storage, authorization) that matter just as much.
What happened
Cloning a keboola.wr-db-snowflake writer config (65 table rows) to point at new destination tables, I built the new config's body like this:
top_params = source_config['configuration']['parameters']
json.dump({'parameters': top_params}, f)
then created it with:
kbagent config new --component-id keboola.wr-db-snowflake --push --no-files \
--configuration-file body.json ...
kbagent config examples --component-id keboola.wr-db-snowflake only shows {"parameters": {"db": {...}}} — nothing in the examples output, config new --help, or the validation step (which I ended up skipping via --no-validate, see below) hinted that runtime was a real, populated sibling key on the source config I was copying from.
The concrete parallelism example
Source config (config detail on the one I was cloning) had this at the configuration root:
{
"parameters": { "db": { "...": "..." } },
"runtime": { "parallelism": "20" }
}
My hand-built clone body only had:
{
"parameters": { "db": { "...": "..." } }
}
kbagent config new --push accepted this with no warning and created a config with no runtime key at all, which Keboola silently treats as parallelism: 1. Result: all 65 writer rows, which should run up to 20-at-a-time, instead ran strictly sequentially in production — a 140-minute run instead of the expected ~60-90 minutes. Nothing errored; it just silently ran 2x+ slower. I only caught it by manually comparing job start/end timestamps per row after the fact (each row's job started the instant the previous one ended — the exact signature of parallelism: 1), not from any tool feedback.
Two independent asks
-
A real clone/duplicate command — e.g. kbagent config clone --project P --component-id C --from-config-id X --name "New Name" [--set path=value ...] — that copies the entire existing configuration object (parameters + runtime + storage + authorization, whatever exists) and only lets you override specific fields, instead of requiring a hand-built replacement body. This removes the whole class of "forgot a sibling key" bugs, not just this one.
-
If (1) isn't planned soon, at minimum: make config examples and/or config new --help explicitly say something like "This shows the parameters shape only — a real configuration may also have runtime, storage, and authorization at the same level; when reconstructing a config from an existing one, copy the whole object, not just parameters." Cheap to add, would have caught this immediately.
Repro / where I hit it
kbagent config examples --component-id keboola.wr-db-snowflake → root examples only show parameters.
kbagent config new --component-id keboola.wr-db-snowflake --push --configuration-file body.json ... with body.json = {"parameters": {...}} → succeeds, silently produces a config with no runtime key at all (confirmed via config detail afterward, and via the production run-time regression above).
- Separately, the same
config new --push --dry-run call failed schema validation with "<root>: 'db' is a required property" even though db was correctly nested under parameters (matching the documented example exactly). Had to pass --no-validate to get past it — which is also what let the missing runtime block through unnoticed. Possibly a related/contributing bug in the AI Service schema validation path — filing this mainly as an FYI, happy to split into its own issue if useful.
Environment
- kbagent v0.79.0 (also reproduced the schema-validation quirk before an in-progress background update to v0.82.0)
- Windows 11, PowerShell/Git Bash
Summary
kbagent config new --pushhas no way to duplicate an existing configuration, so cloning one has to be done by hand-reconstructing the configuration body fromconfig detailoutput. It's very easy to silently drop a sibling top-level key this way — in our caseruntime(specificallyruntime.parallelism) — because nothing inconfig new,config examples, or the docs calls out that a component's root config can have siblings ofparameters(runtime,storage,authorization) that matter just as much.What happened
Cloning a
keboola.wr-db-snowflakewriter config (65 table rows) to point at new destination tables, I built the new config's body like this:then created it with:
kbagent config examples --component-id keboola.wr-db-snowflakeonly shows{"parameters": {"db": {...}}}— nothing in the examples output,config new --help, or the validation step (which I ended up skipping via--no-validate, see below) hinted thatruntimewas a real, populated sibling key on the source config I was copying from.The concrete parallelism example
Source config (
config detailon the one I was cloning) had this at the configuration root:{ "parameters": { "db": { "...": "..." } }, "runtime": { "parallelism": "20" } }My hand-built clone body only had:
{ "parameters": { "db": { "...": "..." } } }kbagent config new --pushaccepted this with no warning and created a config with noruntimekey at all, which Keboola silently treats asparallelism: 1. Result: all 65 writer rows, which should run up to 20-at-a-time, instead ran strictly sequentially in production — a 140-minute run instead of the expected ~60-90 minutes. Nothing errored; it just silently ran 2x+ slower. I only caught it by manually comparing job start/end timestamps per row after the fact (each row's job started the instant the previous one ended — the exact signature ofparallelism: 1), not from any tool feedback.Two independent asks
A real clone/duplicate command — e.g.
kbagent config clone --project P --component-id C --from-config-id X --name "New Name" [--set path=value ...]— that copies the entire existing configuration object (parameters+runtime+storage+authorization, whatever exists) and only lets you override specific fields, instead of requiring a hand-built replacement body. This removes the whole class of "forgot a sibling key" bugs, not just this one.If (1) isn't planned soon, at minimum: make
config examplesand/orconfig new --helpexplicitly say something like "This shows theparametersshape only — a real configuration may also haveruntime,storage, andauthorizationat the same level; when reconstructing a config from an existing one, copy the whole object, not justparameters." Cheap to add, would have caught this immediately.Repro / where I hit it
kbagent config examples --component-id keboola.wr-db-snowflake→ root examples only showparameters.kbagent config new --component-id keboola.wr-db-snowflake --push --configuration-file body.json ...withbody.json = {"parameters": {...}}→ succeeds, silently produces a config with noruntimekey at all (confirmed viaconfig detailafterward, and via the production run-time regression above).config new --push --dry-runcall failed schema validation with"<root>: 'db' is a required property"even thoughdbwas correctly nested underparameters(matching the documented example exactly). Had to pass--no-validateto get past it — which is also what let the missingruntimeblock through unnoticed. Possibly a related/contributing bug in the AI Service schema validation path — filing this mainly as an FYI, happy to split into its own issue if useful.Environment