Tencent/WeKnora · error

resource physical path has unsupported provider scheme

Error message

resource physical path has unsupported provider scheme

What it means

Register parses a provider scheme from the (possibly scope-stripped) physical path via types.ParseProviderScheme. If the path has no recognizable provider prefix (e.g. s3://, gcs://, local filesystem conventions), the resource cannot be attributed to a storage provider and registration fails.

Source

Thrown at internal/application/service/resource.go:74

		return physicalPath, nil
	}
	locationHash := resourceLocationHash(physicalPath)
	existing, err := s.repo.GetByTenantLocation(ctx, tenantID, locationHash)
	if err != nil {
		return "", err
	}
	if existing != nil {
		return types.BuildResourcePath(existing.Handle), nil
	}

	backendID, inner, scoped := types.ParseStorageBackendPath(physicalPath)
	providerPath := physicalPath
	if scoped {
		providerPath = inner
	}
	provider := types.ParseProviderScheme(providerPath)
	if provider == "" {
		return "", fmt.Errorf("resource physical path has unsupported provider scheme")
	}
	lifecycle := types.ResourceLifecyclePersistent
	if meta.Temporary {
		lifecycle = types.ResourceLifecycleTemporary
	}
	for attempt := 0; attempt < 4; attempt++ {
		handle, tokenErr := randomResourceToken()
		if tokenErr != nil {
			return "", tokenErr
		}
		resource := &types.StoredResource{
			Handle:           handle,
			TenantID:         tenantID,
			StorageBackendID: backendID,
			Provider:         provider,
			PhysicalPath:     physicalPath,
			LocationHash:     locationHash,
			Kind:             meta.Kind,

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Prefix the physical path with a supported provider scheme, e.g. 's3://bucket/key' or the local-store scheme used by your deployment.
  2. Check types.ParseProviderScheme to see which schemes are recognized in this version.
  3. Normalize legacy paths through a migration helper that adds the correct scheme.
  4. Update the code path that builds paths so the provider scheme is always included at construction time.

Example fix

// before
physicalPath := fmt.Sprintf("%s/%s", bucket, key) // "mybucket/docs/a.pdf"
// after
physicalPath := fmt.Sprintf("s3://%s/%s", bucket, key) // "s3://mybucket/docs/a.pdf"
Defensive patterns

Strategy: validation

Validate before calling

if types.ParseProviderScheme(strings.TrimSpace(physicalPath)) == "" {
    return fmt.Errorf("path %q needs a provider scheme (e.g. s3://)", physicalPath)
}

Type guard

func hasProviderScheme(p string) bool { return types.ParseProviderScheme(p) != "" }

Try / catch

id, err := svc.Register(ctx, tenantID, path, meta)
if err != nil && strings.Contains(err.Error(), "unsupported provider scheme") {
    return nil, fmt.Errorf("cannot register %q: %w", path, err)
}

Prevention

When it happens

Trigger: Calling Register with a bare relative path like 'uploads/file.pdf' or a URL with an unknown/typo scheme ('s3a://bucket/x' if unsupported, 'file' without '//' form the parser rejects).

Common situations: Constructing physical paths by string concatenation and forgetting the provider prefix; switching storage backends and leaving old unprefixed paths; custom schemes not registered with ParseProviderScheme.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/954c1c3879a5bd8f. Report an issue: GitHub.