neondatabase/neon · warning · ApiError
frequency must be <=1000 Hz
Error message
frequency must be <=1000 Hz
What it means
Returned as HTTP 400 BadRequest by profile_cpu_handler in neon's http-utils when the frequency query parameter of /profile/cpu is >= 1001 Hz. Sampling frequencies above 1000 Hz are rejected to keep profiling overhead and file size sane; the default is 99 Hz and any value up to 1000 is accepted.
Source
Thrown at libs/http-utils/src/endpoint.rs:388
Pprof,
Svg,
}
// Parameters.
let format = match get_query_param(&req, "format")?.as_deref() {
None => Format::Pprof,
Some("pprof") => Format::Pprof,
Some("svg") => Format::Svg,
Some(format) => return Err(ApiError::BadRequest(anyhow!("invalid format {format}"))),
};
let seconds = match parse_query_param(&req, "seconds")? {
None => 5,
Some(seconds @ 1..=60) => seconds,
Some(_) => return Err(ApiError::BadRequest(anyhow!("duration must be 1-60 secs"))),
};
let frequency_hz = match parse_query_param(&req, "frequency")? {
None => 99,
Some(1001..) => return Err(ApiError::BadRequest(anyhow!("frequency must be <=1000 Hz"))),
Some(frequency) => frequency,
};
let force: bool = parse_query_param(&req, "force")?.unwrap_or_default();
// Take the profile.
static PROFILE_LOCK: Lazy<Mutex<()>> = Lazy::new(|| Mutex::new(()));
static PROFILE_CANCEL: Lazy<Notify> = Lazy::new(Notify::new);
let report = {
// Only allow one profiler at a time. If force is true, cancel a running profile (e.g. a
// Grafana continuous profile). We use a try_lock() loop when cancelling instead of waiting
// for a lock(), to avoid races where the notify isn't currently awaited.
let _lock = loop {
match PROFILE_LOCK.try_lock() {
Ok(lock) => break lock,
Err(_) if force => PROFILE_CANCEL.notify_waiters(),
Err(_) => {
return Err(ApiError::Conflict(View on GitHub (pinned to 8f60b04da4)
Solutions
- Lower frequency to <=1000, e.g. ?frequency=250 or keep the default 99
- If you need finer resolution, profile a longer duration instead of a higher frequency
- Verify no profile-frequency default in your scrape config exceeds 1000
Example fix
# before curl 'http://localhost:9898/profile/cpu?frequency=2000' # 400 frequency must be <=1000 Hz # after curl 'http://localhost:9898/profile/cpu?frequency=250'
Defensive patterns
Strategy: validation
Validate before calling
const freq = Number(process.env.PROFILE_FREQUENCY ?? 99);
const safeFreq = Number.isInteger(freq) && freq <= 1000 && freq > 0 ? freq : 99;
await fetch(`/profile/cpu?frequency=${safeFreq}`); Type guard
function isValidProfileFrequency(f) { const n = Number(f); return Number.isInteger(n) && n >= 1 && n <= 1000; } Prevention
- Cap sampling frequency at 1000 Hz client-side; default 99 is usually enough
- Prefer longer windows over higher frequencies for resolution
- Check agent defaults when changing profiling configs
When it happens
Trigger: GET /profile/cpu?frequency=2000 or ?frequency=1001 — any integer of 1001 or more returns this 400.
Common situations: Copy-pasting a pprof tutorial that recommends high frequencies; trying to get finer-grained stacks on an idle system; Grafana agent config with a high sample rate pointed at the endpoint.
Related errors
- invalid format {format}
- duration must be 1-60 secs
- heap profiling not enabled
- Cannot manage failpoints because neon was compiled without f
- Failed to configure failpoints: {err_msg}
AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16).
Data as JSON: /api/errors/8b5e9cc802d3ce8b.
Report an issue: GitHub.