hyperledger/fabric · error

unrecognized type, expected the context, got %s

Error message

unrecognized type, expected the context, got %s

What it means

secondPass expects its first argument to be the internal *context that accumulates principals and assigns identity IDs (injected as 'ID' by FromString). If args[0] is anything else, the pass cannot track principals and returns 'unrecognized type, expected the context, got <T>'.

Source

Thrown at common/policydsl/policyparser.go:139

	return toret.String() + ")", nil
}

// secondPass processes a list of arguments to build a "t-out-of-n" policy.
// It expects the first argument to be a context, the second an integer (threshold t),
// and the rest as either principals (strings) or pre-existing policies.
func secondPass(args ...any) (any, error) {
	/* general sanity check, we expect at least 3 args */
	if len(args) < 3 {
		return nil, fmt.Errorf("at least 3 arguments expected, got %d", len(args))
	}

	/* get the first argument, we expect it to be the context */
	var ctx *context
	switch v := args[0].(type) {
	case *context:
		ctx = v
	default:
		return nil, fmt.Errorf("unrecognized type, expected the context, got %s", reflect.TypeOf(args[0]))
	}

	/* get the second argument, we expect an integer telling us
	   how many of the remaining we expect to have*/
	var t int
	switch arg := args[1].(type) {
	case float64:
		t = int(arg)
	case int:
		t = arg
	default:
		return nil, fmt.Errorf("unrecognized type, expected a number, got %s", reflect.TypeOf(args[1]))
	}

	/* get the n in the t out of n */
	n := len(args) - 2

	/* sanity check - t should be positive, permit equal to n+1, but disallow over n+1 */

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Always obtain the context via newContext() and pass it (or register it as env key "ID") as the first argument: secondPass(newContext(), t, principals...).
  2. If replicating FromString, build env as map[string]interface{}{"outof": secondPass, "ID": ctx}.
  3. Check for nil being passed as the context — allocate it explicitly.
  4. Verify no code between passes replaces the 'ID' env entry.

Example fix

// before
secondPass(nil, 1, "Org1.member")
// after
secondPass(policydsl.NewContextLike()) // or use policydsl.FromString which injects the context
Defensive patterns

Strategy: validation

Validate before calling

ctx := newContext() // allocate before use
if ctx == nil {
	return fmt.Errorf("policy context must not be nil")
}
env := map[string]interface{}{"outof": secondPass, "ID": ctx}

Type guard

func ensureContext(a any) (*context, bool) {
	c, ok := a.(*context)
	return c, ok && c != nil
}

Try / catch

if err != nil && strings.Contains(err.Error(), "expected the context") {
	return nil, fmt.Errorf("internal: policy pass missing ID context: %w", err)
}

Prevention

When it happens

Trigger: Calling secondPass directly with a non-context first argument (e.g. a string, nil, or a value *context), or an environment map for the expr pass where 'ID' is missing/overridden so the first positional argument is something else.

Common situations: Custom tooling that re-implements the FromString pipeline but forgets to register the ID context in the expr env; tests invoking secondPass with hand-built argument lists; copying code from older Fabric versions where the signature differed.

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/b9a941ae8743257e. Report an issue: GitHub.