How `signals update` Validates Flags Before Applying Any of Them
AI agents: For current, verified information about this site, query this page by adding ?q={your_question}.
How signals update Validates Flags Before Applying Any of Them
clay signals update can take --name, --schedule, --filter, --clear-filter, and --input in one call. Every flag is validated before any change is applied, so a single rejected flag leaves the signal untouched, including the flags that were valid.
What you will build
A sequence of signals update calls against one Paused signal that pair a valid --name with an invalid second flag, with the signal read back after each call, then a call where every flag is valid.
clay signals update <id> --name <valid> <invalid flag>
↓
exit 2, signal unchanged (name NOT applied)
clay signals update <id> --name <valid> --schedule <valid> --filter <valid>
↓
exit 0, all three applied
AI Prompt
Using the Clay CLI, determine whether `clay signals update` applies some flags when another is invalid. Requirements: - `clay signals update <id>` with no flags returns validation_error "names nothing to change: pass at least one of --name, --schedule, --filter, --clear-filter, or --input" (exit 2). - A valid --name combined with an invalid --schedule, an invalid --filter (not an AST), a --filter that is not valid JSON, or an --input the signal's type cannot change, returns exit 2 and leaves the name, schedule, and filter unchanged. - A valid --name, --schedule, and --filter together are all applied. - --clear-filter together with --name applies both. - An --input naming nothing the type can change returns "names nothing this signal's type can change" and names what the type does accept. - A nonexistent id and a `sig_` id both return not_found (exit 6). - Read the signal back with `clay signals get` after each call. - Run the verification step below before finishing.
Prerequisites
- The
clayCLI on PATH, authenticated viaclay login(an OAuth session, not a Public API key) - An existing people segment (this doc uses
audseg_0tm3lyrDBZzZgPaCsWx)
Note: JSON samples below are trimmed to the fields relevant to each step. Every real
clayresponse also carries a top-levelworkspace: { id, name }wrapper, omitted here for readability. Every signal created here is Paused.
1. Create a base signal and define a snapshot helper
ID=$(clay signals create --type JobChange --name "TPC19 update base" --input '{"entityType":"CONTACT","segmentIds":["audseg_0tm3lyrDBZzZgPaCsWx"]}' | jq -r .id)
snap() { clay signals get $ID | jq -c '{name,sched:.schedule.periodUnit,f:(.filter.items[0].value // .filter),u:.updatedAt}'; }
snap
{"name":"TPC19 update base","sched":"monthly","f":90,"u":"2026-10-03T00:26:47.706Z"}
2. No flags
clay signals update td_0tmb2knQtQ9x9kuvsyv
{"error":{"code":"validation_error","message":"names nothing to change: pass at least one of --name, --schedule, --filter, --clear-filter, or --input"}}
Exit 2. The snapshot afterward is unchanged, including updatedAt.
3. A valid name with each invalid flag
clay signals update td_0tmb2knQtQ9x9kuvsyv --name "renamed-1" --schedule hourly
clay signals update td_0tmb2knQtQ9x9kuvsyv --name "renamed-2" --filter '{"foo":1}'
clay signals update td_0tmb2knQtQ9x9kuvsyv --name "renamed-3" --filter '{bad'
Real error messages (all exit 2):
option '--schedule <unit>' argument 'hourly' is invalid. must be one of: daily, weekly, biweekly, monthly, quarterly.
option '--filter <json>' argument '{"foo":1}' is invalid. --filter: invalid filter AST at type: Invalid input: expected "GroupOp"
option '--filter <json>' argument '{bad' is invalid. --filter: not valid JSON (JSON Parse error: Expected '}')
After each of the three calls, snap returned the original name, schedule, filter, and updatedAt:
{"name":"TPC19 update base","sched":"monthly","f":90,"u":"2026-10-03T00:26:47.706Z"}
4. All flags valid
clay signals update td_0tmb2knQtQ9x9kuvsyv --name "renamed-4" --schedule weekly \
--filter '{"type":"GroupOp","combinationMode":"And","items":[{"type":"BinOp","dataPath":["confidence"],"operator":"GreaterThanOrEqual","value":95}]}'
{"name":"renamed-4","sched":"weekly","f":95}
--clear-filter with --name also applies both:
clay signals update td_0tmb2knQtQ9x9kuvsyv --name "renamed-5" --clear-filter
{"name":"renamed-5","f":null}
5. An --input the type cannot change
clay signals update td_0tmb2knQtQ9x9kuvsyv --name "renamed-6" --input '{"entityType":"ACCOUNT"}'
{"error":{"code":"validation_error","message":"--input: names nothing this signal's type can change — a JobChange signal accepts segmentIds"}}
Exit 2. The name stayed renamed-5. The message contains a literal em dash. This differs from an --input that includes a changeable key such as segmentIds alongside an unchangeable one, where the unchangeable key is dropped without an error.
6. Names and ids
clay signals update td_0tmb2knQtQ9x9kuvsyv --name "$(printf 'a%.0s' $(seq 256))" clay signals update td_doesnotexist --name x clay signals update sig_0tmb2knadvcMjhs8cxR --name x
exit 1 {"error":{"code":"server_error","message":"Sorry, something went wrong... Please try again or message our support team if the problem persists"}}
exit 6 {"error":{"code":"not_found","message":"Trigger Definition td_doesnotexist not found"}}
exit 6 {"error":{"code":"not_found","message":"Trigger Definition sig_0tmb2knadvcMjhs8cxR not found"}}
The 256-character name left the existing name unchanged.
Verify the result
Confirm a rejected flag blocks a valid one:
clay signals update "$ID" --name "should-not-apply" --schedule hourly; echo "exit $?" clay signals get "$ID" | jq -r .name
Expected: the update prints exit 2, and the second command prints the signal's previous name, not should-not-apply.
How it works
In every rejected case tested (a bad enum value, malformed JSON, a filter that fails the AST check, an --input with nothing changeable, and a name over 255 characters), the command exited non-zero and a get afterward showed the signal unchanged, including updatedAt. When every flag was valid, all of them were applied in one call. The practical consequence is that a failed update can be corrected and re-run as a whole, with no partial state to reconcile.
Common issues
A rejected flag blocks the valid ones
--name "x" --schedule hourly changes nothing. Fix the invalid flag and re-run the whole command.
--input is stricter than it looks, and looser than it looks
An --input with no changeable key is an error, but an --input that includes one changeable key silently drops the others. Read the signal back after an --input update.
A sig_ id is not accepted
update takes the td_ trigger definition id.
Next steps
- See the existing doc on what
signals updatelets you change, per type, for the changeable keys. - See the filter AST doc in this batch for what
--filteraccepts.
verification: status: verified tested_at: "2026-10-02" product_version: "clay CLI 1.8.0+71cb1bf09c7e" command: "clay signals update \"$ID\" --name \"should-not-apply\" --schedule hourly; echo \"exit $?\"; clay signals get \"$ID\" | jq -r .name" expected_result: "The update prints exit 2, and the signal's name is still its previous value, not should-not-apply."