Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Telegraf By James Joyner IV · · 9 min read

Telegraf Error Guide: '[processors.starlark] ... error in Starlark' — Fix Starlark Script Errors

Quick answer

Fix Telegraf's [processors.starlark] script error: repair the apply() function, handle None fields and types, avoid unsupported Python features, and debug metric mutation with telegraf --test.

  • #telegraf
  • #metrics
  • #troubleshooting
  • #errors
Free toolkit

Fixing errors like this? Get 500 free DevOps AI prompts

500 copy-paste AI prompts for the stack you actually run — one PDF, free.

Overview

The starlark processor runs a small Python-like script against every metric. When the script raises at runtime, Telegraf logs the error with the file/line inside the Starlark source and drops the metric being processed:

2026-07-10T12:00:00Z E! [processors.starlark] Error in plugin: fields.star:7:23: in apply: unknown binding: cpu_total

Type errors are equally common — Starlark is strict about mixing types and about None:

E! [processors.starlark] Error in plugin: transform.star:12: unsupported binary op: float + NoneType

A script that fails to load at startup prevents Telegraf from starting at all, while a runtime error inside apply() drops individual metrics.

Symptoms

  • Metrics that pass through the starlark processor are missing or unmodified, and the log shows Error in plugin: <file>.star:<line>.
  • Telegraf fails to start entirely when the script has a load-time syntax error.
  • Errors reference apply, unknown binding, unsupported binary op, or NoneType.
  • The script works on some metrics but fails on others (those missing an expected field).
  • Adding a new tag/field in Starlark silently produces nothing because apply() returned None.

Common Root Causes

  • apply() does not return the metric — forgetting return metric drops every metric silently.
  • Accessing a field/tag that may not existmetric.fields["cpu_total"] raises unknown binding/key not found when absent.
  • Type mismatches — arithmetic between a float field and a None, or between a string and an int.
  • Using unsupported Python — Starlark has no while, no recursion, no import, no f-strings, and a limited stdlib; copied Python fails to load.
  • Mutating during iteration — changing metric.fields while iterating over it raises a runtime error.
  • Load-time syntax errors — indentation or a construct Starlark rejects, which blocks agent startup.
  • Returning the wrong typeapply() must return a metric, a list of metrics, or None (to drop); anything else errors.

Diagnostic Workflow

Isolate the processor with a file input containing a representative sample so you can iterate quickly without live data:

# /tmp/starlark-test.conf
[[inputs.file]]
  files = ["/tmp/sample.lp"]
  data_format = "influx"

[[processors.starlark]]
  script = "/etc/telegraf/scripts/transform.star"

[[outputs.file]]
  files = ["stdout"]
printf 'cpu,host=web01 usage_user=12.5,usage_system=3.1\n' > /tmp/sample.lp
telegraf --config /tmp/starlark-test.conf --test --debug

Write defensive Starlark that guards missing fields and always returns the metric:

# /etc/telegraf/scripts/transform.star
def apply(metric):
    u = metric.fields.get("usage_user")
    s = metric.fields.get("usage_system")
    # Guard against missing fields (None) before arithmetic
    if u != None and s != None:
        metric.fields["usage_busy"] = u + s
    metric.tags["team"] = "platform"
    return metric        # MUST return the metric (or None to drop)

Reference the script from your real config and re-test the whole pipeline:

[[processors.starlark]]
  script = "/etc/telegraf/scripts/transform.star"

Use the log module inside Starlark to trace values during development:

load("logging.star", "log")   # available in recent Telegraf builds

def apply(metric):
    log.debug("fields: {}".format(metric.fields))
    return metric

Example Root Cause Analysis

A processor meant to compute a busy percentage worked in testing but flooded the log with unsupported binary op: float + NoneType in production. The script did metric.fields["busy"] = metric.fields["usage_user"] + metric.fields["usage_system"]. In the lab, every sample had both fields; in production, some hosts occasionally reported only usage_user (the other field was absent that interval), so metric.fields["usage_system"] returned None and the addition failed, dropping the metric.

The fix was to fetch fields with .get() and guard for None before arithmetic, exactly as shown in the diagnostic block above. After deploying the defensive version, the errors stopped and metrics with only one field passed through unmodified instead of being dropped. The lesson: Starlark scripts run against real, messy data where fields come and go — never assume a field exists, always use .get(), and always return metric.

Prevention Best Practices

  • Always end apply() with return metric (or an explicit None when you intend to drop); a missing return silently drops everything.
  • Read fields and tags with .get() and guard for None before any arithmetic or string operation.
  • Test every script against a file input with representative samples — including edge cases with missing fields — before deploying.
  • Remember Starlark is not Python: no import, no while, no recursion, no f-strings; use .format() and load() for modules.
  • Never mutate metric.fields/metric.tags while iterating over them; collect changes first, then apply.
  • Keep scripts small and pure; move complex logic upstream into the producing service where you have a full language.

Quick Command Reference

# Isolate the processor with a file input and sample metric
printf 'cpu,host=web01 usage_user=12.5\n' > /tmp/sample.lp
telegraf --config /tmp/starlark-test.conf --test --debug

# Validate the whole config after editing the script
telegraf --config /etc/telegraf/telegraf.conf --test --debug

# Watch Starlark runtime errors live
journalctl -u telegraf -f | grep -i starlark

# Confirm version (Starlark features vary by release)
telegraf --version

Conclusion

[processors.starlark] ... error in Starlark points at a script bug: a missing return metric, access to an absent field, a type mismatch with None, or unsupported Python. Isolate the processor with a file input and sample metrics, write defensively with .get() and None guards, and always return the metric. Because Starlark runs against real, variable data, testing against edge cases — not just the happy path — is what keeps the pipeline from silently dropping metrics.

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.