AlistGo/alist · error
IsTruncated nil
Error message
IsTruncated nil
What it means
Thrown by the S3 driver's legacy ListObjects V1 pagination loop after a successful ListObjects call whose response body omitted the IsTruncated field. The AWS SDK models IsTruncated as a *bool, so a provider that simply does not return it yields nil, and the driver aborts instead of guessing whether more pages exist. It is a defect/quirk of S3-compatible providers rather than of real AWS S3, which always sets the field.
Source
Thrown at drivers/s3/util.go:135
}
for _, object := range listObjectsResult.Contents {
if strings.HasSuffix(*object.Key, "/") {
continue
}
name := path.Base(*object.Key)
if !args.S3ShowPlaceholder && (name == getPlaceholderName(d.Placeholder) || name == d.Placeholder) {
continue
}
file := &model.Object{
//Id: *object.Key,
Name: name,
Size: *object.Size,
Modified: *object.LastModified,
}
files = append(files, model.WrapObjStorageClass(file, aws.StringValue(object.StorageClass)))
}
if listObjectsResult.IsTruncated == nil {
return nil, errors.New("IsTruncated nil")
}
if *listObjectsResult.IsTruncated {
marker = *listObjectsResult.NextMarker
} else {
break
}
}
return files, nil
}
func (d *S3) listV2(prefix string, args model.ListArgs) ([]model.Obj, error) {
prefix = getKey(prefix, true)
files := make([]model.Obj, 0)
var continuationToken, startAfter *string
for {
input := &s3.ListObjectsV2Input{
Bucket: &d.Bucket,
ContinuationToken: continuationToken,View on GitHub (pinned to 843d9dc814)
Solutions
- Switch the storage config to list_version = v2 (ListObjectsV2), which uses ContinuationToken and does not depend on IsTruncated
- Upgrade the S3-compatible gateway (MinIO/Ceph) to a version that fully populates IsTruncated in V1 responses
- Patch listV1 to treat a nil IsTruncated as 'not truncated' via aws.BoolValue(listObjectsResult.IsTruncated) when the result set is smaller than the page size
Example fix
// before
if listObjectsResult.IsTruncated == nil {
return nil, errors.New("IsTruncated nil")
}
if *listObjectsResult.IsTruncated {
marker = *listObjectsResult.NextMarker
} else {
break
}
// after (defensive: nil treated as end of listing)
if aws.BoolValue(listObjectsResult.IsTruncated) && listObjectsResult.NextMarker != nil {
marker = *listObjectsResult.NextMarker
} else {
break
} Defensive patterns
Strategy: validation
Validate before calling
// before switching to list v1, probe the provider
out, err := s3client.ListObjects(&s3.ListObjectsInput{Bucket: aws.String(bucket), MaxKeys: aws.Int64(1)})
if err != nil { return err }
if out.IsTruncated == nil {
// provider omits IsTruncated: use ListObjectsV2 for this storage
return configureListVersion("v2")
} Type guard
func hasTruncationFlag(out *s3.ListObjectsOutput) bool {
return out != nil && out.IsTruncated != nil
} Try / catch
// in a wrapper around List
files, err := d.List(ctx, dir, args)
if err != nil && strings.Contains(err.Error(), "IsTruncated nil") {
log.Warn("provider omits IsTruncated; switching storage to list_version=v2")
setStorageListVersion("v2") // next List call succeeds
files, err = d.List(ctx, dir, args)
} Prevention
- Prefer list_version=v2 for any non-AWS S3 endpoint
- Test new S3-compatible endpoints with a one-object listing before mounting large buckets
- Patch listV1 defensively with aws.BoolValue so nil means 'done'
When it happens
Trigger: Listing a bucket with list_version=v1 against an S3-compatible endpoint (some MinIO/Ceph/vendor gateways) that returns <ListBucketResult> without <IsTruncated>. The very first page (or any later page) then triggers this error before pagination can continue.
Common situations: Self-hosted MinIO or Ceph RGW endpoints, NAS vendor 'S3' services, or older gateway firmware that implement the V1 API incompletely; also misconfigured custom endpoint_url pointing at such a gateway. Real AWS, and list_version v2 (ListObjectsV2 uses different pagination fields), never hit it.
Related errors
- faild to get ETag from header
- faild to get ETag from header
- s3 transition task manager is not initialized
- up status: %d, error: %s
- upload failed after %d retries due to server errors
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/3a9de198374deb42.
Report an issue: GitHub.