projectdiscovery/katana · warning

unknown tag %q

Error message

unknown tag %q

What it means

formatTemplate wraps a sentinel errUnknownTag with the offending tag name when a fasttemplate placeholder in the output template does not exist among the result's fields ({{...}} tags not found in fieldsMap). Notably, the writer intentionally swallows this case and returns (nil, nil), ignoring unknown tags and skipping that output line.

Source

Thrown at pkg/output/format_template.go:28

)

func (w *StandardWriter) formatTemplate(output *Result) ([]byte, error) {
	var fieldOutputs []fieldOutput
	fieldNames := strings.Join(FieldNames, ",")
	fieldOutputs = formatField(output, fieldNames)
	fieldOutputs = append(fieldOutputs, getValueForCustomField(output)...)

	fieldsMap := make(map[string]string)
	for _, fo := range fieldOutputs {
		fieldsMap[fo.field] = fo.value
	}

	errUnknownTag := errors.New("unknown tag")

	tagFn := fasttemplate.TagFunc(func(w io.Writer, tag string) (int, error) {
		value, ok := fieldsMap[tag]
		if !ok {
			return 0, fmt.Errorf("%w %q", errUnknownTag, tag)
		}
		return w.Write([]byte(value))
	})

	out, err := w.outputTemplate.ExecuteFuncStringWithErr(tagFn)
	if err != nil {
		if errors.Is(err, errUnknownTag) {
			// If there is an unknown tag, we just ignore it.
			return nil, nil
		}
		return nil, err
	}

	return []byte(out), nil
}

View on GitHub (pinned to e3e742739c)

Solutions

  1. Fix the template to use only supported fields (see output.FieldNames) or define the custom field
  2. If custom code calls formatTemplate directly, match errors.Is(err, errUnknownTag) and ignore as the library does
  3. Test the template on a single result to catch typos early

Example fix

// before
template: "[{{url}}] {{statuz}}" // typo
// after
template: "[{{url}}] {{status}}"
Defensive patterns

Strategy: validation

Validate before calling

func validateTemplate(tmpl string) error {
    for _, tag := range extractTags(tmpl) {
        if !slices.Contains(output.FieldNames, tag) && !isCustomField(tag) {
            return fmt.Errorf("unknown template tag: %s", tag)
        }
    }
    return nil
}

Type guard

func isUnknownTag(err error) bool {
    return err != nil && strings.Contains(err.Error(), "unknown tag")
}

Try / catch

out, err := w.formatTemplate(result)
if err != nil && errors.Is(err, errUnknownTag) {
    return nil, nil // ignore unknown tags, as the library does
}

Prevention

When it happens

Trigger: Using -f/-output-template (or custom template options) with a tag like {{nonexistent-field}} that is not in FieldNames nor a custom field (format_template.go:28).

Common situations: Typo in template field names ({{rul}} instead of {{url}}); using custom-field placeholders that were never defined; copying templates across katana versions where field names changed.

Related errors


AI-assisted analysis of projectdiscovery/katana@e3e742739c (2026-09-03). Data as JSON: /api/errors/b6ae1e37e7e2b841. Report an issue: GitHub.