projectdiscovery/nuclei · error

failed to build request parser: %w

Error message

failed to build request parser: %w

What it means

grpcurl.RequestParserAndFormatter could not be built for the request message. The parser is created with AllowUnknownFields=false and FormatJSON, so syntactically invalid JSON, or JSON containing fields that do not exist in the method's request schema, fails at this point; an unresolvable input type for the method also surfaces here.

Source

Thrown at pkg/js/libs/grpc/invoke.go:138

	cleanup := func() { refClient.Reset() }
	return grpcurl.DescriptorSourceFromServer(ctx, refClient), cleanup, nil
}

// invokeUnary invokes a unary (or single-response) gRPC method described by src
// over cc, marshaling the JSON request and formatting the JSON response.
func invokeUnary(ctx context.Context, src grpcurl.DescriptorSource, cc *grpc.ClientConn, method, requestJSON string, headers []string) (string, error) {
	body := strings.TrimSpace(requestJSON)
	if body == "" {
		body = "{}"
	}
	var in io.Reader = strings.NewReader(body)

	parser, formatter, err := grpcurl.RequestParserAndFormatter(grpcurl.FormatJSON, src, in, grpcurl.FormatOptions{
		EmitJSONDefaultFields: true,
		AllowUnknownFields:    false,
	})
	if err != nil {
		return "", fmt.Errorf("failed to build request parser: %w", err)
	}

	var out bytes.Buffer
	handler := &grpcurl.DefaultEventHandler{
		Out:       &out,
		Formatter: formatter,
	}

	if err := grpcurl.InvokeRPC(ctx, src, cc, method, headers, handler, parser.Next); err != nil {
		return "", err
	}
	if handler.Status != nil && handler.Status.Code() != codes.OK {
		return "", fmt.Errorf("grpc status %s: %s", handler.Status.Code().String(), handler.Status.Message())
	}
	return strings.TrimRight(out.String(), "\n"), nil
}

// describeSymbol returns the textual descriptor for a fully-qualified symbol.

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. Pass strict JSON with schema-exact field names: client.Invoke('grpc.health.v1.Health/Check', '{"service":""}')
  2. Inspect the schema first: const d = client.DescribeSymbol('acme.v1.Svc/Get') and copy field names/types exactly
  3. Use '{}' when no fields need setting (an empty message is already defaulted to {})

Example fix

// before: single-quoted pseudo-JSON and wrong field name
client.Invoke('acme.v1.User/Get', "{'id': 1}");

// after: strict JSON with the field name from DescribeSymbol
client.Invoke('acme.v1.User/Get', JSON.stringify({ userId: 1 }));
Defensive patterns

Strategy: validation

Validate before calling

let body = {};
try {
  body = message ? JSON.parse(message) : {};
} catch (e) {
  throw new Error(`request is not strict JSON: ${e.message}`);
}
const resp = client.Invoke(method, JSON.stringify(body));

Type guard

const isStrictJson = (s) => { try { JSON.parse(s); return true; } catch { return false; } };

Try / catch

try { const resp = client.Invoke(method, msg); }
catch (e) {
  if (/failed to build request parser/.test(e.message || '')) {
    // fix JSON syntax, then verify field names against DescribeSymbol output
  }
}

Prevention

When it happens

Trigger: client.Invoke('acme.v1.Svc/Get', "{'id': 1}") (single quotes / trailing comma); message fields not present in the .proto ('{"user_id":1}' when the field is 'userId'); wrong method name so the request type cannot be resolved from the descriptor source.

Common situations: Hand-writing request JSON instead of copying field names from DescribeSymbol; schema drift between the protoset/reflection schema and the one the author inspected; JSON built by string concatenation instead of JSON.stringify.

Related errors


AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15). Data as JSON: /api/errors/85f6aa3d205d85fe. Report an issue: GitHub.