juicedata/juicefs · critical

Failed to put: %s

Error message

Failed to put: %s

What it means

During format-time connectivity testing, the initial Put of a test object failed with an error containing 'denied', indicating the credentials lack write permission to the target bucket. The command aborts rather than attempting bucket creation, since the failure is authorization, not existence.

Source

Thrown at cmd/format.go:337

	}
	return false
}

var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")

func randSeq(n int) string {
	b := make([]rune, n)
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	for i := range b {
		b[i] = letters[r.Intn(len(letters))]
	}
	return string(b)
}

func doTesting(ctx context.Context, store object.ObjectStorage, key string, data []byte) error {
	if err := store.Put(ctx, key, bytes.NewReader(data)); err != nil {
		if strings.Contains(strings.ToLower(err.Error()), "denied") {
			return fmt.Errorf("Failed to put: %s", err)
		}
		if err2 := store.Create(ctx); err2 != nil {
			if strings.Contains(err.Error(), "NoSuchBucket") {
				return fmt.Errorf("Failed to create bucket %s: %s, previous error: %s\nPlease create bucket %s manually, then format again.",
					store, err2, err, store)
			} else {
				return fmt.Errorf("Failed to create bucket %s: %s, previous error: %s",
					store, err2, err)
			}
		}
		if err := store.Put(ctx, key, bytes.NewReader(data)); err != nil {
			return fmt.Errorf("Failed to put: %s", err)
		}
	}
	// GLACIER storage class doesn't allow read after write
	if _, ok := ctx.Value(object.TierKey{}).(uint8); ok {
		return nil
	}

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Grant write access to the principal (e.g. attach s3:PutObject to the IAM policy or MinIO write policy)
  2. Check the bucket policy for explicit Deny statements on PutObject
  3. If the bucket enforces SSE-KMS, ensure the key policy allows the principal, or configure server-side encryption settings
  4. Verify with the AWS/MinIO CLI: `aws s3 cp testfile s3://bucket/test`

Example fix

// before (IAM policy)
{"Effect":"Deny","Action":"s3:PutObject","Resource":"arn:aws:s3:::mybucket/*"}
// after
{"Effect":"Allow","Action":"s3:PutObject","Resource":"arn:aws:s3:::mybucket/*"}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check write access with provider CLI
// aws s3api put-object --bucket mybucket --key write-test --body /dev/null

Type guard

func isAccessDenied(err error) bool {
    return err != nil && strings.Contains(strings.ToLower(err.Error()), "denied")
}

Try / catch

err := doTesting(ctx, store, key, data)
if err != nil && strings.Contains(strings.ToLower(err.Error()), "denied") {
    // fix IAM/bucket policy before retrying
}

Prevention

When it happens

Trigger: `juicefs format` against an object store whose access keys have read-only policy (e.g. IAM user without s3:PutObject), a bucket with PutObject denied by bucket policy, or a MinIO user without write policy on the path.

Common situations: AWS IAM policies restricting PutObject; bucket policies denying the principal; MinIO canned policies like `readonly`; KMS/encryption policies blocking unencrypted puts.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/0c2a332b7337b2dd. Report an issue: GitHub.