rtk-ai/rtk · error
Trae PreToolUse value is not an array
Error message
Trae PreToolUse value is not an array
What it means
Trae hooks.json validation step three: if the `hooks` object contains a PreToolUse entry (`PRE_TOOL_USE_KEY`), its value must be a JSON array of hook commands. If it exists with another type (object, string, number), rtk bails because it appends its hook to that array and cannot merge into any other shape.
Solutions
- Wrap the PreToolUse value in an array: `"PreToolUse": [<existing-hook>]`.
- If unsure, back up the file, remove the PreToolUse key, and rerun `rtk init` so rtk writes a correct array entry.
- Validate the JSON structure against a known-good Trae hooks.json before rerunning.
Example fix
// before (.trae/hooks.json)
{ "version": 1, "hooks": { "PreToolUse": { "command": "foo" } } }
// after
{ "version": 1, "hooks": { "PreToolUse": [ { "command": "foo" } ] } } Defensive patterns
Strategy: validation
Validate before calling
const fs = require('fs');
function preToolUseIsArray(p = '.trae/hooks.json') {
if (!fs.existsSync(p)) return true;
const j = JSON.parse(fs.readFileSync(p, 'utf8'));
const v = j?.hooks?.PreToolUse;
return v === undefined || Array.isArray(v);
} Type guard
const preToolUseOk = (j) => j?.hooks?.PreToolUse === undefined || Array.isArray(j.hooks.PreToolUse);
Try / catch
match rtk init result { Err if msg contains 'PreToolUse value is not an array' => wrap the value in an array and retry } Prevention
- Always model PreToolUse as an array of hook objects, even for a single hook.
- Lint .trae config files in CI with a structural check.
- Reset to `{"version":1,"hooks":{}}` and let rtk init write the hook when unsure.
When it happens
Trigger: Running `rtk init` for Trae where existing `.trae/hooks.json` has `hooks.PreToolUse` present but not an array (e.g. a single object instead of an array of hook entries).
Common situations: User or another tool wrote PreToolUse as a single hook object instead of an array; hand-edit flattened the list; template copied from a tool with a different hooks schema.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Trae hooks.json version must be 1
- Trae hooks value is not an object
- validated object
- Failed to uninstall RTK from one or more Droid hook files
- hook stdin exceeds byte limit
AI-assisted analysis of rtk-ai/rtk@0924356b4c (2026-09-19).
Data as JSON: /api/errors/e5eccf6151a5d515.
Report an issue: GitHub.
Appendix: source
Thrown at src/hooks/init.rs:5109
.context("Trae hooks.json root must be an object")?;
if root_object
.get("version")
.is_some_and(|version| version != &serde_json::json!(1))
{
anyhow::bail!("Trae hooks.json version must be 1");
}
if root_object
.get("hooks")
.is_some_and(|hooks| !hooks.is_object())
{
anyhow::bail!("Trae hooks value is not an object");
}
if root_object
.get("hooks")
.and_then(|hooks| hooks.get(PRE_TOOL_USE_KEY))
.is_some_and(|pre_tool_use| !pre_tool_use.is_array())
{
anyhow::bail!("Trae PreToolUse value is not an array");
}
Ok(())
}
/// Install RTK's Trae hook in every supplied target. All targets are read and
/// parsed before any write, so malformed `.trae` or `.trae-cn` configuration
/// cannot cause a partially-applied update.
fn patch_trae_hooks_json_paths(paths: &[PathBuf], ctx: InitContext) -> Result<Vec<PatchResult>> {
struct PendingPatch {
path: PathBuf,
existed: bool,
serialized: String,
}
let mut results = Vec::with_capacity(paths.len());
let mut pending = Vec::new();
let mut applied: Vec<String> = Vec::new();
View on GitHub (pinned to 0924356b4c)