Error messages
Every message Signal Lab can show when something fails, by its code: the code is what a run's report, the command line and the API give. Values in braces are filled in with what failed.
api
| Code | Message |
|---|---|
api.not_found | The server has no such address — the interface and the server are different versions |
api.run_invalid | The run request cannot be read |
api.run_source | Name the experiment once: a document or a template |
api.template_unknown | There is no bundled template {name} |
auth
| Code | Message |
|---|---|
auth.host | This server does not answer to that address — open it by its own name |
auth.origin | This request came from another site and was refused |
auth.required | Sign in to this server first |
broadcast
| Code | Message |
|---|---|
broadcast.cidr_invalid | {value} is not a CIDR block — use a.b.c.d/nn, e.g. 192.168.1.0/24 |
broadcast.interface_invalid | {value} is not an IPv4 address — enter the interface's address, or leave it empty for any |
broadcast.ipv6 | IPv6 has no broadcast — use multicast instead |
broadcast.join_failed | Cannot join the multicast group {group} |
broadcast.not_broadcast | {target} is not a broadcast address — use 255.255.255.255:port or x.x.x.255:port |
broadcast.not_multicast | {target} is not a multicast group — use an address from 224.0.0.0 to 239.255.255.255 |
broadcast.port_shared | {target} is already in use — turn on “share the port” to listen alongside it |
broadcast.prefix_invalid | /{value} is not a prefix length — use /0 to /32 |
broadcast.rate_invalid | The beacon rate must be above 0 |
broadcast.rate_limit | {pps} packets/s across {targets} targets is over the {max} pps limit — lower the rate or narrow the target |
broadcast.reply_missing | There is no reply to send — set one, or turn off “answer probes” |
broadcast.sweep_port | Set the port to sweep |
broadcast.sweep_too_large | /{prefix} spans {count} addresses, and a sweep reaches at most {max} hosts — narrow it to /{limit} or a smaller block |
broadcast.target_required | Enter at least one target |
check
| Code | Message |
|---|---|
check.body_missing | The response does not contain {text} |
check.body_truncated | The response ({bytes} B) is longer than the 256 KiB kept, so the text could not be checked |
check.header_mismatch | Header {name} is {actual}, which does not contain {text} |
check.header_missing | The response has no {name} header |
check.latency_failed | The response took {actual} ms, over the {limit} ms limit |
check.no_response | No HTTP response before this step — put an HTTP request before it on every path |
check.status_failed | Expected HTTP {expected}, received {actual} |
check.value_failed | Expected: {value} {op} {expected} |
cli
| Code | Message |
|---|---|
cli.bind_one | --bind sets the address of one emulator; several were given |
cli.emulate_nothing | Nothing to emulate: the files hold no emulator |
cli.emulator_unknown | {name} is not a file, and {path} has no emulator by that id or name |
cli.file_unknown | {name} is neither a file nor a bundled template — signallab templates lists them |
cli.header_invalid | {value} is not a header — use 'Name: value' |
cli.library_missing | There is no library at {path} — the app makes it the first time it starts; or name one with --library |
cli.matrix_conflict | {name} is set twice — by --param and the matrix, or by --matrix and the file; give it once |
cli.matrix_file_invalid | {path} is not a matrix: an object of NAME: [values], or a list of objects of NAME: value |
cli.matrix_invalid | {value} is not NAME=V1,V2 |
cli.matrix_too_large | {n} combinations — at most {max} from one command |
cli.matrix_too_wide | {axes} axes multiply past any count — at most {max} combinations from one command |
cli.matrix_unknown | --matrix {name}: no experiment given has a parameter by that name |
cli.matrix_value_invalid | {name}: a matrix value is text, a number or true/false |
cli.osc_arg_invalid | {value} is not an OSC argument — use i:3, f:0.5, d:1.5, h:64, s:text, b:hex, T, F or N |
cli.param_invalid | {value} is not NAME=VALUE |
cli.server_ended | The answer from {url} ended before the run did |
cli.server_invalid | {url} is not a server address — use one like http://127.0.0.1:1430 |
cli.server_reply | {url} answered with something that is not Signal Lab's (HTTP {status}) |
cli.server_unreachable | Cannot reach the server at {url} |
cli.signal_ambiguous | Several signals are called {name} — name one by its id: {ids} |
cli.signal_unknown | No signal {name} in {path} |
cli.status_unexpected | The response was {actual}, not {expected} |
cli.token_empty | The token file {path} is empty |
command
| Code | Message |
|---|---|
command.args_invalid | The engine could not read the arguments of {name} — the interface and the engine are different versions |
command.json_required | The server takes commands only as JSON |
command.reply_invalid | The engine could not encode its answer |
command.unknown | The engine has no command {name} — the interface is newer than the engine |
compare
| Code | Message |
|---|---|
compare.not_numbers | {value} and {expected} must both be numbers for this comparison |
details
| Code | Message |
|---|---|
details | Technical details |
doc
| Code | Message |
|---|---|
doc.connection_duplicate | The connection {from} → {to} appears twice |
doc.connection_invalid | Connection {from} → {to} leads to a missing node or back to itself |
doc.name_required | Give the experiment a name |
doc.node_count | An experiment holds 1–{max} nodes |
doc.node_id_duplicate | Two nodes share the id {id} |
doc.node_id_empty | A node has an empty id |
doc.port_invalid | Unknown output {port} |
doc.position_invalid | The node has an invalid position |
doc.start_end_count | An experiment needs exactly one Start and one End |
doc.version_unsupported | File version {version} is not supported; this version of Signal Lab reads version {supported} |
emulator
| Code | Message |
|---|---|
emulator.accept_failed | Taking connections on {target} stopped with an error |
emulator.arg_value | {value} is not a value of type {type} |
emulator.args_too_many | At most {max} arguments |
emulator.bind_taken | {target} is taken by another emulator of this experiment ({other}) |
emulator.body_failed | The request body could not be read |
emulator.body_too_large | The request body is larger than {max} KB |
emulator.busy | More than {max} replies are waiting — this one was dropped |
emulator.conditions_too_many | At most {max} conditions |
emulator.failed | The emulator stopped unexpectedly |
emulator.header_value_invalid | Not a valid header value — it may not hold line breaks |
emulator.headers_too_many | At most {max} headers |
emulator.mqtt_client_id | Refused a client without an id that asked to keep its session |
emulator.mqtt_login | Refused {client}: wrong user name or password |
emulator.mqtt_password_alone | MQTT 3.1.1 cannot carry a password without a user name, so no client could connect: set a user name too |
emulator.mqtt_protocol | Refused a client speaking {protocol} level {level}: this broker speaks MQTT 3.1.1 (level 4) |
emulator.name_unknown | Unknown name {{{name}}} — a reply reads {{request…}} and parameters |
emulator.node_unknown | There is no emulator {id} in this experiment |
emulator.not_in_run | Emulator {id} is not part of this run |
emulator.not_running | Emulator #{id} is not running |
emulator.params_only | Only text and parameters here: it is fixed when the emulator starts, before anything arrives |
emulator.path_param | {value} is not a segment name — use :name with letters, digits and _ |
emulator.path_rest | * can only be the whole last segment, as in /files/* |
emulator.path_slash | A path starts with / |
emulator.response_required | A route needs at least one response |
emulator.responses_too_many | At most {max} responses |
emulator.rules_too_many | At most {max} rules |
emulator.secret_unsupported | An emulator cannot read secrets |
emulator.weights_zero | At least one response needs a weight above 0 |
emulators
| Code | Message |
|---|---|
emulators.encode | The emulator library could not be written as JSON |
emulators.json_invalid | {path} is not a valid emulator file: JSON error at line {line}, column {column} — fix the file or remove it |
extract
| Code | Message |
|---|---|
extract.header_missing | The response has no {name} header |
extract.json_missing | {path} is not in the response |
extract.no_match | /{pattern}/ did not match the response body |
extract.not_json | The response body is not JSON |
extract.truncated | The response ({bytes} B) is longer than the 256 KiB kept, so the value cannot be read reliably |
feedback
| Code | Message |
|---|---|
feedback.disabled | Feedback is not being taken right now — write to info@proanima.net |
feedback.email_invalid | That is not an e-mail address |
feedback.failed | The feedback service answered HTTP {status} |
feedback.file_too_large | {name} is larger than {max_mb} MB |
feedback.file_type | {name}: a screenshot must be PNG, JPEG, WebP or GIF, and a log text |
feedback.invalid | The feedback service did not accept the form |
feedback.message_required | Write a message first |
feedback.message_too_long | The message is longer than {max} characters |
feedback.rate_limited | Too many messages from this address for now — try again in {retry_after_s} s |
feedback.send_failed | The feedback service could not pass the message on to the mail server; try again later (reference {id}) |
feedback.too_large | Everything together is larger than {max_mb} MB |
feedback.too_many_files | At most {max} logs |
file
| Code | Message |
|---|---|
file.encode | The experiment could not be written as JSON |
file.io | Cannot read or write {path} |
file.json_invalid | Not a valid experiment file: JSON error at line {line}, column {column} |
file.not_found | {path} is not a file in the server's data folder |
file.too_large | Experiment files are at most {max} MiB |
firewall
| Code | Message |
|---|---|
firewall.declined | Administrator rights were not given, so the firewall was not changed |
firewall.failed | The firewall's rules could not be read or changed |
firewall.server | A server's firewall is set on the server: run signallab firewall allow there, or ask its administrator |
firewall.unsupported | There is no per-program firewall to change here — open the ports in ufw or firewalld |
graph
| Code | Message |
|---|---|
graph.cycle | This node is part of a cycle; only a Loop's body may lead back to it |
graph.needs_http | Needs an HTTP request before it on every path |
graph.outputs_required | Connect the required outputs |
graph.port_unexpected | Output {port} does not belong to this node |
graph.start_input | Start cannot have an input |
graph.unreachable | Not reachable from Start |
hex
| Code | Message |
|---|---|
hex.empty | No bytes to send — enter pairs of hex digits such as de ad be ef |
hex.invalid | {value} is not hex bytes — use pairs of digits such as de ad be ef |
http
| Code | Message |
|---|---|
http.client_failed | The HTTP client could not be started |
http.digest_invalid | The server asked for Digest without a realm or nonce |
http.digest_not_offered | The server answered 401 without asking for Digest |
http.digest_other_origin | The request was sent on to {origin}, which asked for Digest — only the origin the request names is answered |
http.digest_unsupported | The server asked for Digest with {algorithm}, which Signal Lab does not speak (it speaks MD5 and SHA-256) |
http.duration_invalid | The duration must be 0 or more seconds |
http.rate_invalid | The rate must be 0 or {min}–{max} requests/s |
impair
| Code | Message |
|---|---|
impair.bind_taken | {target} is already {other}'s: two of the run's sockets cannot share a port |
impair.loop | The relay's packets would come back to it through {target} and circle forever — point its target at the device |
impair.not_running | Impairment {id} is not part of this run |
impair.relay_unknown | There is no Impairment {id} in this experiment |
inspect
| Code | Message |
|---|---|
inspect.empty | The capture is empty — nothing to save |
inspect.frame_gone | Frame #{seq} is no longer in the capture: newer frames took its place |
inspect.no_payload | Frame #{seq} recorded only its size, not its bytes |
json_path
| Code | Message |
|---|---|
json_path.invalid | {path} is not a JSON path — use $.field, $.items[0] or $["a b"] |
load
| Code | Message |
|---|---|
load.nothing_planned | This profile sends no requests |
load.spike_outside | The spike must end within the duration |
load.steps_out_of_range | Every step's rate must be 0–{max} requests/s |
load.threshold | {metric} was {actual}, the threshold {op} {value} |
load.threshold_value | A threshold needs a number, 0 or more |
load.thresholds_too_many | At most {max} thresholds |
load.too_long | The steps take longer than a run may last ({seconds} s) |
loop
| Code | Message |
|---|---|
loop.body_entered | Only a Loop's Body output may lead into its body |
loop.body_leaves | Inside a Loop's body every output leads on in the body or back to the Loop |
loop.body_parallel | Inside a Loop's body an output has one wire: an iteration runs as one branch |
loop.body_unsupported | Start, End, parallel branches, joins and other loops cannot be inside a Loop's body |
loop.limit | Iterations: {max}; the exit condition never held (wire Limit to carry on) |
loop.no_return | Nothing on Body leads back to this Loop |
mqtt
| Code | Message |
|---|---|
mqtt.client_id_required | Enter a client ID — brokers refuse an empty one |
mqtt.filter_required | Add at least one topic filter |
mqtt.no_answer | {broker} accepted the connection but did not answer in time — is it an MQTT broker? |
mqtt.not_connected | Connection #{id} is not open — connect to the broker first |
mqtt.protocol | {broker} answered with something other than MQTT 3.1.1 |
mqtt.refused | {broker} refused the connection (return code {code}) |
mqtt.refused_client_id | {broker} rejected the client ID — choose another one |
mqtt.refused_credentials | {broker} rejected the username or password |
mqtt.refused_not_authorized | {broker} did not authorize this client — check its access rules |
mqtt.refused_protocol | {broker} does not accept MQTT 3.1.1 clients |
mqtt.refused_unavailable | {broker} is unavailable right now — try again later |
mqtt.subscribe_refused | {broker} refused the subscription to {filter} |
mqtt.topic_invalid | This topic cannot be published to |
mqtt.topic_required | Enter a topic to publish to |
name
| Code | Message |
|---|---|
name.no_value | {name} has no value |
name.not_on_every_path | {{{name}}} is not set on every path before this step |
name.unknown | Unknown name {{{name}}} — add a parameter or extract a variable |
netsim
| Code | Message |
|---|---|
netsim.not_running | The relay {id} is not running any more |
node
| Code | Message |
|---|---|
node.bind_invalid | {value} is not a listening address — use IP:port, e.g. 0.0.0.0:9001 |
node.header_invalid | {value} is not a valid header name |
node.load_alone | Load replaces Repeat and Retry: turn those off |
node.load_unsupported | Only an HTTP request can run under load |
node.method_invalid | {value} is not an HTTP method |
node.not_found | Node {id} no longer exists |
node.osc_address | OSC addresses start with / ({value}) |
node.params_only | Only parameters can be used here — the run subscribes before its first step |
node.range | Must be {min}–{max} |
node.repeat_too_long | The repeats take longer than a run may last ({seconds} s) |
node.repeat_too_many | More than {max} sends: make the interval longer or the time shorter |
node.repeat_unsupported | Only steps that send can repeat |
node.required | Required |
node.retry_unsupported | Only steps that send or listen can retry |
node.rules_too_many | At most {max} argument rules |
node.target_invalid | {value} is not an address with a port, e.g. 127.0.0.1:9000 |
node.too_long | Too long: at most {max} |
node.topic_filter | {value} is not a topic filter: + stands for a whole level, # only for the whole last one |
node.topic_wildcard | A publish topic cannot contain the wildcards + or # |
node.url_invalid | {value} is not an http:// or https:// URL |
osc
| Code | Message |
|---|---|
osc.packet_malformed | Malformed OSC packet ({bytes} B) |
osc.pattern_char | “{char}” is not allowed here in an OSC address |
osc.pattern_empty_segment | Empty part between slashes |
osc.pattern_empty_set | Empty [ ] set |
osc.pattern_range | The range {range} runs backwards |
osc.pattern_slash | An OSC address pattern starts with / |
osc.pattern_too_long | The address pattern is longer than {max} characters |
osc.pattern_unclosed | Unclosed [ or { |
param
| Code | Message |
|---|---|
param.duplicate | Parameter {name} is defined twice |
param.name_invalid | Parameter name “{name}” must start with a letter or _ and use only letters, digits and _ |
param.name_reserved | “{name}” is reserved and cannot name a parameter |
param.too_large | Parameter {name} is larger than {max} KiB |
param.unknown | Unknown parameter {name} |
params
| Code | Message |
|---|---|
params.too_many | At most {max} parameters |
position
| Code | Message |
|---|---|
position | position {position} |
profile
| Code | Message |
|---|---|
profile.active_missing | The active profile {name} does not exist |
profile.duplicate | Profile {name} is defined twice |
profile.name_invalid | Profile names are 1–{max} characters |
profile.unknown_param | Profile {profile} sets {name}, which is not a parameter |
profile.values_too_many | Profile {profile} sets more than {max} values |
profiles
| Code | Message |
|---|---|
profiles.too_many | At most {max} profiles |
regex
| Code | Message |
|---|---|
regex.invalid | {pattern} is not a valid regular expression |
run
| Code | Message |
|---|---|
run.join_waiting | Join is still waiting for {count} branch(es) — a wire into it was never followed, for instance a branch that took another path |
run.limit_range | A run may take 1 to {max} seconds |
run.no_end | The run stopped before reaching End |
run.node_missing | Node {id} is missing |
run.not_a_check | This node is not a check |
run.not_a_wait | This node is not a wait |
run.not_an_action | This node does not send or listen |
run.override_unknown | Run with… sets {name}, which is not a parameter |
run.timeout | The run took longer than {seconds} s and was stopped |
runs
| Code | Message |
|---|---|
runs.name_invalid | “{name}” is not a run's report |
runs.not_found | No run “{name}”: its report was removed |
scan
| Code | Message |
|---|---|
scan.host_required | Enter the host to scan |
secret
| Code | Message |
|---|---|
secret.empty | A secret cannot be empty |
secret.missing | Secret {name} is not stored on this computer — set it under Parameters → Secrets |
secret.name_invalid | Secret name “{name}” must start with a letter or _, use only letters, digits and _, and be at most {max} characters |
secret.read_only | Secrets are read-only here: set {name} on the server (SIGNALLAB_SECRET_{name}, or a file named {name} in its secrets folder) |
secret.store | The system credential store failed for {name} |
secret.too_large | A secret is at most {max} KiB |
secret.unsupported | Secrets are kept in the Windows Credential Manager, which this system does not have |
seed
| Code | Message |
|---|---|
seed.range | The seed must be 0–{max} |
show
| Code | Message |
|---|---|
show | Show |
signals
| Code | Message |
|---|---|
signals.encode | The signal library could not be written as JSON |
signals.json_invalid | {path} is not a valid signal library: JSON error at line {line}, column {column} — fix the file or remove it |
socket
| Code | Message |
|---|---|
socket.option_failed | The system did not accept the socket option {option} |
template
| Code | Message |
|---|---|
template.arg_empty | Empty argument |
template.arg_integer | {function}: {value} is not a whole number |
template.arg_invalid | The argument {value} must be quoted |
template.arg_number | {function}: {value} is not a number |
template.arg_quote | Unclosed quote in the arguments |
template.args_pick | pick(…) needs at least one option |
template.args_random_float | random_float(min, max[, digits]) takes 2 or 3 arguments |
template.args_random_int | random_int(min, max) takes 2 arguments |
template.args_uuid | uuid() takes no arguments |
template.bad_call | {text} is not a valid function call |
template.bad_name | {text} is not a valid name |
template.bad_path | {text}: invalid path — use .field, [0] or ["key"] |
template.digits | random_float takes 0–{max} digits |
template.empty | Empty {{ }} |
template.needs_name | {head} needs a name: {head}.NAME |
template.no_field | {name} has no field {path} |
template.node_fields | node has only node.id |
template.now_fields | now has only now.iso |
template.range | {function}: min {min} must be below max {max} |
template.run_fields | run has only run.id and run.seed |
template.unclosed | Unclosed {{ |
template.unknown_function | Unknown function {name}() |
transport
| Code | Message |
|---|---|
transport.address_in_use | {target} is already in use by another program |
transport.address_unavailable | {target} is not an address of this computer |
transport.denied | The system or a firewall did not allow access to {target} |
transport.dns | Cannot resolve {target} — check the host name |
transport.failed | Sending to {target} failed |
transport.refused | {target} refused the connection — nothing is listening on that port |
transport.reset | {target} closed the connection |
transport.target_invalid | {target} is not a valid address |
transport.timeout | No answer from {target} in time |
transport.tls | A secure connection to {target} could not be made (certificate or TLS) |
transport.unreachable | {target} is unreachable — check the network and the address |
unknown
| Code | Message |
|---|---|
unknown | Unexpected engine error ({code}) |
variable
| Code | Message |
|---|---|
variable.name_invalid | Variable name “{name}” must start with a letter or _ and use only letters, digits and _ |
variable.name_reserved | “{name}” is reserved and cannot name a variable |
variable.shadows_param | Variable {name} has the same name as a parameter |
wait
| Code | Message |
|---|---|
wait.bind_failed | Cannot listen on {target} |
wait.not_listening | Not listening on {target} |
wait.receive_failed | Listening on {target} stopped with an error |
wait.timeout | No matching message within {ms} ms ({unmatched} other messages arrived on {target}) |
ws
| Code | Message |
|---|---|
ws.close_code | {code} is not a close code a client sends — use 1000, or 3000–4999 for the application's own |
ws.closed | The WebSocket connection is closed ({code}) |
ws.connection_after | {id} does not come before this step — it opens the connection this step uses |
ws.connection_unknown | {id} is not a WebSocket connect node of this experiment |
ws.handshake_failed | The WebSocket upgrade with {url} failed |
ws.handshake_status | {url} answered HTTP {status} instead of switching to WebSocket |
ws.header_invalid | The header {name} cannot be sent with the upgrade |
ws.message_too_large | A WebSocket message is limited to {max} bytes |
ws.not_connected | No open WebSocket connection {id} |
ws.payload_required | Give the message as text or as hex bytes |
ws.protocol_error | The connection with {url} broke: the server did not keep to the WebSocket protocol |
ws.protocol_invalid | {value} is not a subprotocol name: no spaces, commas or slashes |
ws.subprotocol_refused | {url} did not take any of the subprotocols offered |
ws.url_invalid | {url} is not a WebSocket address — use ws://host:port/path or wss://… |
Fields
The names a message gives to the field it is about.
| Field | Name |
|---|---|
address | Address |
argument | Argument |
attempts | Attempts |
auth | Authentication |
bind | Listen on |
body | Body |
broker | Broker |
burst_length | Burst length |
burst_start | Burst loss |
code | Close code |
condition | Condition |
conditions | Conditions |
connection | Connection |
corrupt | Corruption |
delay_ms | Delay |
duplicate | Duplication |
duration_s | Duration |
emulator | Emulator |
expected | Expected |
expected_text | Expected text |
fallback | Requests no route takes |
greeting | Greeting |
header_name | Header name |
header_value | Header value |
headers | Headers |
hex | Hex bytes |
host | Host |
jitter_ms | Jitter |
json_path | JSON path |
latency_ms | Latency |
listen | Listen on |
load | Load |
load_base | Base rate |
load_concurrency | Concurrency |
load_duration | Duration |
load_every | Step length |
load_from | From |
load_peak | Peak rate |
load_rate | Rate |
load_spike | Spike |
load_step | Step |
load_steps | Steps |
load_to | To |
loop_max | Iterations |
loss | Packet loss |
max_ms | Time limit |
message | Message |
method | Method |
ms | Duration |
name | Name |
outage_down | Down for |
outage_up | Up for |
password | Password |
path | Path |
pattern | Pattern |
payload | Payload |
port | Port |
profile_name | Profile name |
protocols | Subprotocols |
qos | QoS |
rate | Rate |
rate_kbps | Bandwidth |
reason | Reason |
relay | Impairment |
reorder | Reordering |
repeat | Repeat |
repeat_count | Number of sends |
repeat_duration | Repeat for |
repeat_interval | Interval |
repeat_jitter | Jitter |
reply | Reply |
reply_address | Reply address |
reply_arg | Reply argument |
reply_args | Reply arguments |
reply_bind | Reply on |
reply_pattern | Reply pattern |
reply_payload | Reply payload |
reply_topic | Reply topic |
reset | Connection reset |
responses | Responses |
retained | Retained messages |
retry | Retry |
retry_delay | Pause between attempts |
rule | Rule |
rule_value | Rule value |
rules | Rules |
stall | Half-open |
status | Status |
target | Target |
threshold | Threshold |
thresholds | Thresholds |
timeout_ms | Timeout |
to | Reply to |
token | Token |
topic | Topic |
url | URL |
username | User name |
value | Value |
variable | Variable |
weight | Weight |