googleapis/mcp-toolbox · error

unable to bind: %w

Error message

unable to bind: %w

What it means

ps.Bind(params.AsMap()) failed when converting the runtime-supplied parameter values to the prepared statement's bound form. This happens when the provided values don't match the declared parameter types/count (e.g. string where integer declared, missing or extra params) or a value is of a Go type the client cannot encode.

Source

Thrown at internal/sources/bigtable/bigtable.go:185

func (s *Source) RunSQL(ctx context.Context, statement string, configParam parameters.Parameters, params parameters.ParamValues) (any, error) {
	mapParamsType, err := getMapParamsType(configParam)
	if err != nil {
		return nil, fmt.Errorf("fail to get map params: %w", err)
	}

	ps, err := s.BigtableClient().PrepareStatement(
		ctx,
		statement,
		mapParamsType,
	)
	if err != nil {
		return nil, fmt.Errorf("unable to prepare statement: %w", err)
	}

	bs, err := ps.Bind(params.AsMap())
	if err != nil {
		return nil, fmt.Errorf("unable to bind: %w", err)
	}

	out := []any{}
	var rowErr error
	err = bs.Execute(ctx, func(resultRow bigtable.ResultRow) bool {
		vMap := make(map[string]any)
		cols := resultRow.Metadata.Columns

		for _, c := range cols {
			var columValue any
			if err = resultRow.GetByName(c.Name, &columValue); err != nil {
				rowErr = err
				return false
			}
			vMap[c.Name] = columValue
		}

		out = append(out, vMap)

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Check the wrapped error for which parameter failed to bind
  2. Ensure the caller supplies every declared parameter with the correct type (string vs integer vs array)
  3. Verify params order/naming matches the tool's declared parameters in tools.yaml
  4. Add explicit type coercion/validation at the tool level (e.g. declare type: integer and validate input before invoke)

Example fix

// before
{"user_id": "123"}   // declared integer
// after
{"user_id": 123}     // integer matching Int64SQLType
Defensive patterns

Strategy: validation

Validate before calling

func validateParamValues(declared parameters.Parameters, values map[string]any) error {
	for _, p := range declared {
		v, ok := values[p.GetName()]
		if !ok {
			return fmt.Errorf("missing value for param %q", p.GetName())
		}
		switch p.GetType() {
		case "integer":
			if _, ok := v.(int64); !ok && !isIntLike(v) {
				return fmt.Errorf("param %q must be integer, got %T", p.GetName(), v)
			}
		case "string":
			if _, ok := v.(string); !ok {
				return fmt.Errorf("param %q must be string, got %T", p.GetName(), v)
			}
		case "array":
			if _, ok := v.([]any); !ok {
				return fmt.Errorf("param %q must be array, got %T", p.GetName(), v)
			}
		}
	}
	return nil
}

Type guard

func isIntLike(v any) bool {
	switch v.(type) {
	case int, int32, int64, float64:
		return true
	}
	return false
}

Try / catch

out, err := src.RunSQL(ctx, stmt, cfgParams, values)
if err != nil {
	if strings.Contains(err.Error(), "unable to bind") {
		// reject the request with a parameter type/count mismatch message
	}
	return err
}

Prevention

When it happens

Trigger: RunSQL calls ps.Bind(params.AsMap()) with a params map whose keys or value types don't satisfy the prepared statement's declared SQLTypes (from getMapParamsType).

Common situations: Client (LLM) supplies a param value of the wrong type at invocation time; tool config expects a param the caller omitted; array param passed a non-array value; auth/instrumentation middleware injecting mismatched param sets.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/bdba388460d4abd4. Report an issue: GitHub.