infiniflow/ragflow · error · Exception

Can't find variable: '{cpn_id}@{var_nm}'

Error message

Can't find variable: '{cpn_id}@{var_nm}'

What it means

When the canvas resolves a variable reference of the form '{component_id@output.param.path}', it looks up the source component by id. If no component with that id exists in the DSL, this Exception is raised during get_variable_value — the reference points at a deleted or renamed node.

Source

Thrown at agent/canvas.py:255

            last = m.end()

        out_parts.append(value[last:])
        return "".join(out_parts)

    def get_variable_value(self, exp: str) -> Any:
        exp = exp.strip("{").strip("}").strip(" ").strip("{").strip("}")
        if exp.find("@") < 0:
            return self.globals[exp]
        # Split from the left with maxsplit=1 so the trailing var_nm can
        # legitimately contain '@' characters (defensive: although the
        # upstream regex in `get_value_with_variable` constrains `var_nm`
        # to `[A-Za-z0-9_.-]+`, direct callers of this method may pass
        # any string and should not raise `ValueError: too many values
        # to unpack`). `cpn_id` is system-generated and never contains '@'.
        cpn_id, var_nm = exp.split("@", 1)
        cpn = self.get_component(cpn_id)
        if not cpn:
            raise Exception(f"Can't find variable: '{cpn_id}@{var_nm}'")
        parts = var_nm.split(".", 1)
        root_key = parts[0]
        rest = parts[1] if len(parts) > 1 else ""
        root_val = cpn["obj"].output(root_key)

        if not rest:
            return root_val
        return self.get_variable_param_value(root_val, rest)

    def get_variable_param_value(self, obj: Any, path: str) -> Any:
        cur = obj
        if not path:
            return cur
        for key in path.split("."):
            if cur is None:
                return None

            if isinstance(cur, str):

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Open the canvas and find the node whose param still references the deleted component id; rebind it to an existing component or delete the stale reference.
  2. Search the DSL JSON for the cpn_id shown in the error to locate every stale reference.
  3. If copy-pasting between workflows, re-wire the pasted node's references to components that exist in the target canvas.
  4. Add a lint pass over the DSL (all '@' references resolve to existing component ids) before running.

Example fix

# before
params = {"content": "{deadbeef@output.text}"}  # deadbeef was deleted

# after
params = {"content": "{live1234@output.text}"}  # rebind to existing node
Defensive patterns

Strategy: validation

Validate before calling

def check_references(dsl):
    ids = set(dsl['components'].keys())
    bad = []
    for k, cpn in dsl['components'].items():
        for v in extract_refs(cpn['obj'].get('params', {})):  # finds '{id@...}' tokens
            if v.split('@', 1)[0] not in ids:
                bad.append((k, v))
    return bad  # empty list == safe

Type guard

def ref_resolves(exp: str, component_ids: set) -> bool:
    return '@' not in exp or exp.strip('{} ').split('@', 1)[0] in component_ids

Try / catch

try:
    value = canvas.get_variable_value(exp)
except Exception as e:
    if str(e).startswith("Can't find variable:"):
        # stale reference: surface which node/param held it and fail fast
        raise WorkflowIntegrityError(str(e)) from e
    raise

Prevention

When it happens

Trigger: Any component param containing a reference like '{abc123@output.text}' where 'abc123' is not a key in dsl['components'] — typical after deleting a node that other nodes still reference, or hand-editing component ids.

Common situations: Deleting an upstream component without cleaning references to it; copy-pasting nodes between canvases (ids don't travel with valid targets); race where the canvas is edited while a run is starting; typos in manually written reference expressions.

Related errors


AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15). Data as JSON: /api/errors/df71155fce53a295. Report an issue: GitHub.