pocketbase/pocketbase · error

reached the max recursion level of view collection file fiel

Error message

reached the max recursion level of view collection file field queries

What it means

FindRecordByViewFile walks a chain of nested view collections (a view whose query selects a file field of another view, and so on) to find the real backing collection. A guard limits this walk to 5 levels to prevent infinite recursion when views reference each other circularly. This error means the chain exceeded 5 nested view hops before reaching a non-view file field.

Source

Thrown at core/view.go:218

}

// FindRecordByViewFile returns the original Record of the provided view collection file.
func (app *BaseApp) FindRecordByViewFile(viewCollectionModelOrIdentifier any, fileFieldName string, filename string) (*Record, error) {
	view, err := getCollectionByModelOrIdentifier(app, viewCollectionModelOrIdentifier)
	if err != nil {
		return nil, err
	}

	if !view.IsView() {
		return nil, errors.New("not a view collection")
	}

	var findFirstNonViewQueryFileField func(int) (*queryField, error)
	findFirstNonViewQueryFileField = func(level int) (*queryField, error) {
		// check the level depth to prevent infinite circular recursion
		// (the limit is arbitrary and may change in the future)
		if level > 5 {
			return nil, errors.New("reached the max recursion level of view collection file field queries")
		}

		queryFields, err := parseQueryToFields(app, view.ViewQuery)
		if err != nil {
			return nil, err
		}

		for _, item := range queryFields {
			if item.collection == nil ||
				item.original == nil ||
				item.field.GetName() != fileFieldName {
				continue
			}

			if item.collection.IsView() {
				view = item.collection
				fileFieldName = item.original.GetName()
				return findFirstNonViewQueryFileField(level + 1)

View on GitHub (pinned to 5d217ddb50)

Solutions

  1. Flatten the view hierarchy: make the top view query select the file field directly from a base (non-view) collection instead of through intermediate views.
  2. Break any cycle: ensure no view's query, transitively, references itself.
  3. If you genuinely need more depth, reduce nesting by consolidating the intermediate views' filters/joins into one query.

Example fix

-- before: view_on_view_on_view ... >5 levels deep
CREATE VIEW `deepView` AS SELECT file FROM `view5`;

-- after: select from the base collection directly
CREATE VIEW `deepView` AS SELECT file FROM `baseCollection`;
Defensive patterns

Strategy: validation

Try / catch

if _, err := app.FindRecordByViewFile(v, f, fn); err != nil {
    if strings.Contains(err.Error(), "max recursion level") {
        // notify: view nesting too deep or circular; flatten hierarchy
    }
}

Prevention

When it happens

Trigger: A view A selecting a file field from view B, which selects from view C, etc. more than 5 levels deep; or two views that (directly or transitively) select from each other, creating a cycle, so the resolver can never reach a base collection.

Common situations: Incrementally stacking views on top of views during reporting/refactoring until the depth limit is crossed; circular view definitions introduced by editing a view query in the admin UI to reference another view that already references the first.

Related errors


AI-assisted analysis of pocketbase/pocketbase@5d217ddb50 (2026-08-15). Data as JSON: /api/errors/6834159207d7ad8d. Report an issue: GitHub.