Open Closed

Volo.AIManagement.BackgroundJobs.IndexDocumentJob fails for tenant uploads — blob path mismatch caused by missing IMultiTenant on IndexDocumentJobArgs #10688


User avatar
0
manas-patnaik_HON created

ABP / module versions:

Volo.AIManagement.VectorStores.Pgvector 10.2.0 Volo.Abp.BlobStoring.Azure 10.2.0 All other Volo packages 10.2.0 ABP Framework 10.x (matching) .NET 10.0 DB: SQL Server (Azure SQL), background-jobs provider: default Volo.Abp.BackgroundJobs.EntityFrameworkCore


When a non-host (saas tenant) user uploads a Workspace Data Source PDF, the file is correctly stored in Azure Blob Storage under the multi-tenant path:

triarch-blobs/tenants/{tenantId}/{workspaceId}/{dataSourceId}.pdf …but IndexDocumentJob runs ~minutes later as host and looks up the blob without the tenants/{tenantId}/ prefix, producing:

Volo.Abp.AbpException: Could not find the requested BLOB '{workspaceId}/{dataSourceId}.pdf' in the container 'workspace-data-sources'! at Volo.Abp.BlobStoring.BlobContainer.GetAsync(...) at Volo.AIManagement.BackgroundJobs.IndexDocumentJob.ExecuteAsync(IndexDocumentJobArgs args) The job retries until TryCount = 10, then is abandoned. The DataSource row exists in the DB and the blob exists in Azure — only the path the indexer resolves is wrong.

  • Steps to reproduce the issue:

BackgroundJobExecuter.GetJobArgsTenantId(object jobArgs) in Volo.Abp.BackgroundJobs.Abstractions:

protected virtual Guid? GetJobArgsTenantId(object jobArgs) { return jobArgs switch { IMultiTenant multiTenantJobArgs => multiTenantJobArgs.TenantId, _ => CurrentTenant.Id }; } AbpBackgroundJobs table has no TenantId column (by design — BackgroundJobRecord does not implement IMultiTenant). So the only mechanism to carry tenant from enqueue → execute is the args class implementing IMultiTenant.

We inspected the queued args in AbpBackgroundJobs.JobArgs for our failing job:

{"dataSourceId":"c4b5d4f3-a627-e1f5-a9ab-3a2168f8944b"} — no tenantId field. Therefore IndexDocumentJobArgs does not implement IMultiTenant. The executer falls into the _ => CurrentTenant.Id branch on the worker thread (host context, CurrentTenant.Id == null), so ExecuteAsync runs as host and the blob naming normalizer omits the tenants/{tenantId}/ prefix.

Markdown supported.
Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)

2 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    • Your analysis is correct: ABP background jobs execute under the tenant determined by BackgroundJobExecuter.GetJobArgsTenantId(jobArgs), and when the args don’t implement IMultiTenant, the executer falls back to CurrentTenant.Id (which is typically null on the worker), so the job runs in host context.
    • With Azure Blob Storing, the blob name is tenant-scoped by default: it prefixes the blob path with tenants/<tenant-id> when the current tenant is not null. So running the indexing job in host context makes it look under the wrong blob key.

    What to do (workaround you can apply now)

    1. Ensure the job args carries the TenantId by implementing IMultiTenant and including TenantId in the serialized args.
    2. Enqueue the job with TenantId populated from the current tenant at upload time.

    Example (conceptual fix):

    using System;
    using Volo.Abp.MultiTenancy;
    
    public class IndexDocumentJobArgs : IMultiTenant
    {
        public Guid? TenantId { get; set; }
        public Guid DataSourceId { get; set; }
    }
    

    When enqueueing:

    await _backgroundJobManager.EnqueueAsync(
        new IndexDocumentJobArgs
        {
            TenantId = _currentTenant.Id,
            DataSourceId = dataSourceId
        }
    );
    

    This makes BackgroundJobExecuter switch to that tenant before calling ExecuteAsync, so the blob provider will resolve the correct tenants/<tenantId>/... prefix.

    If you can’t change the args type (alternate workaround)

    Wrap the job execution with an explicit tenant change (only works if you can determine tenantId from DB by DataSourceId without requiring tenant context, e.g., host-visible table or query with disabled filter):

    using (_currentTenant.Change(tenantId))
    {
        // read blob + index
    }
    

    Notes / expectation

    Given how ABP blob naming works, the job must run under the same tenant that uploaded the blob (or you must disable multi-tenancy for that blob container, which would change the storage layout and isolation semantics).

    References

    • Azure blob name calculation (tenant prefix rules): https://abp.io/docs/latest/framework/infrastructure/blob-storing/azure
    • Changing tenant context (ICurrentTenant.Change): https://abp.io/docs/latest/framework/architecture/multi-tenancy#change-the-current-tenant

    This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    enisn created
    Support Team .NET Developer

    Hi,

    Thanks for reporting this issue.

    You are right that AI Management is not intended to work as a tenant-scoped feature. The problem was caused by the workspace-data-sources blob container still using tenant-aware blob storage behavior.

    We have confirmed and fixed this issue by configuring that container as shared instead of tenant-scoped and it'll be published in the next patch release.

    As a temporary workaround on your project, you can configure the same container as shared in one of your application's module ConfigureServices methods:

    using Volo.Abp.BlobStoring;
    using Volo.AIManagement;
    
    public override void ConfigureServices(ServiceConfigurationContext context)
    {
        Configure<AbpBlobStoringOptions>(options =>
        {
            options.Containers.Configure<WorkspaceDataSourceBlobContainer>(container =>
            {
                container.IsMultiTenant = false;
            });
        });
    }
    

    Please note that this changes the resolved blob path from tenant-scoped to shared/host-scoped. So if you already uploaded documents under tenants/<tenant-id>/..., those existing files may need to be re-uploaded after applying the workaround.

    This fix will be included in the next patch release.

    Best regards,

    ABP Support Team

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.8.0-preview. Updated on September 24, 2026, 12:09
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.