kopia/kopia · error

ResolvePolicy

Error message

ResolvePolicy

What it means

ResolvePolicy() POSTs to 'policy/resolve?<target params>' to get the effective (merged) policy. Any request failure is wrapped as "ResolvePolicy". It indicates the resolve request failed rather than the policy being undefined.

Solutions

  1. Confirm server connectivity and that both sides support policy/resolve.
  2. Check the SourceInfo used for policyTargetURLParameters is valid and properly encoded.
  3. Unwrap the error for the HTTP status to distinguish 404/405 (endpoint missing) from transport errors.
  4. Retry after transient connectivity failures.

Example fix

// before
res, err := serverapi.ResolvePolicy(ctx, cli, si, req)
if err != nil { return err }
// after
res, err := serverapi.ResolvePolicy(ctx, cli, si, req)
if err != nil {
    return errors.Wrapf(err, "resolving policy for %v", si)
}
Defensive patterns

Strategy: try-catch

Validate before calling

if req == nil { return errors.New("nil ResolvePolicyRequest") }
if si.Host == "" { return errors.New("missing host in policy target") }

Type guard

func isResolvePolicyErr(err error) bool { return err != nil && strings.Contains(err.Error(), "ResolvePolicy") }

Try / catch

resp, err := serverapi.ResolvePolicy(ctx, cli, si, req)
if err != nil {
    return nil, errors.Wrapf(err, "resolve policy for %v", si)
}

Prevention

When it happens

Trigger: Calling serverapi.ResolvePolicy against an unreachable server, with a ResolvePolicyRequest the server rejects, or malformed target URL parameters from the SourceInfo.

Common situations: Anonymous test callers resolving policies before the server is connected; source paths with characters that break the query string; server without the policy/resolve endpoint (version mismatch).

Related errors


AI-assisted analysis of kopia/kopia@82495e54b5 (2026-09-07). Data as JSON: /api/errors/bb6ca7f5a22a8ffc. Report an issue: GitHub.

Appendix: source

Thrown at internal/serverapi/client_wrappers.go:196

	return fmt.Sprintf("userName=%v&host=%v&path=%v", si.UserName, si.Host, si.Path)
}

// SetPolicy sets the policy.
func SetPolicy(ctx context.Context, c *apiclient.KopiaAPIClient, si snapshot.SourceInfo, pol *policy.Policy) error {
	resp := &Empty{}
	if err := c.Put(ctx, "policy?"+policyTargetURLParameters(si), pol, resp); err != nil {
		return errors.Wrap(err, "SetPolicy")
	}

	return nil
}

// ResolvePolicy resolves the policy.
func ResolvePolicy(ctx context.Context, c *apiclient.KopiaAPIClient, si snapshot.SourceInfo, req *ResolvePolicyRequest) (*ResolvePolicyResponse, error) {
	resp := &ResolvePolicyResponse{}

	if err := c.Post(ctx, "policy/resolve?"+policyTargetURLParameters(si), req, resp); err != nil {
		return nil, errors.Wrap(err, "ResolvePolicy")
	}

	return resp, nil
}

// ListTasks lists the tasks.
func ListTasks(ctx context.Context, c *apiclient.KopiaAPIClient) (*TaskListResponse, error) {
	resp := &TaskListResponse{}
	if err := c.Get(ctx, "tasks", nil, resp); err != nil {
		return nil, errors.Wrap(err, "ListTasks")
	}

	return resp, nil
}

// GetObject returns the object payload.
func GetObject(ctx context.Context, c *apiclient.KopiaAPIClient, objectID string) ([]byte, error) {
	var b []byte

View on GitHub (pinned to 82495e54b5)