juicedata/juicefs · error

can not generate different endpoint using %s

Error message

can not generate different endpoint using %s

What it means

NewSharded builds N storage clients by formatting the endpoint template with the shard index (fmt.Sprintf(endpoint, i)). If the resulting endpoint still contains a leftover format artifact (the check detects the '%!(EXTRA int=0)' Sprintf output), the endpoint string was not a valid template with a %d verb, meaning all shards would get the same endpoint — which defeats sharding — so it fails fast.

Source

Thrown at pkg/object/sharding.go:234

func (s *sharded) AbortUpload(ctx context.Context, key string, uploadID string) {
	s.pick(key).AbortUpload(ctx, key, uploadID)
}

func (s *sharded) CompleteUpload(ctx context.Context, key string, uploadID string, parts []*Part) error {
	return s.pick(key).CompleteUpload(ctx, key, uploadID, parts)
}

func (s *sharded) Restore(ctx context.Context, key string, days int32) error {
	return s.pick(key).Restore(ctx, key, days)
}

func NewSharded(name, endpoint, ak, sk, token string, shards int) (ObjectStorage, error) {
	stores := make([]ObjectStorage, shards)
	var err error
	for i := range stores {
		ep := fmt.Sprintf(endpoint, i)
		if strings.HasSuffix(ep, "%!(EXTRA int=0)") {
			return nil, fmt.Errorf("can not generate different endpoint using %s", endpoint)
		}
		stores[i], err = CreateStorage(name, ep, ak, sk, token)
		if err != nil {
			return nil, err
		}
	}
	return &sharded{stores: stores}, nil
}

var _ SupportTier = (*sharded)(nil)
var _ ObjectStorage = (*sharded)(nil)

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Add a %d verb to the endpoint, e.g. endpoint="http://shard%d.example.com", so each shard gets a distinct address.
  2. Ensure the endpoint string has no stray format verbs/arguments that leave EXTRA output; keep it a simple single-%d template.
  3. If sharding is not desired, use the plain storage type instead of sharded.

Example fix

// before
CreateStorage("sharded", "http://shard.example.com", ak, sk, "")
// after (valid sharded endpoint template)
NewSharded("sharded", "http://shard%d.example.com", ak, sk, "", 4)
Defensive patterns

Strategy: validation

Validate before calling

if !strings.Contains(endpoint, "%d") {
    return fmt.Errorf("sharded endpoint must contain a %%d placeholder: %s", endpoint)
}

Try / catch

store, err := object.NewSharded(name, endpoint, ak, sk, "", shards)
if err != nil && strings.Contains(err.Error(), "can not generate different endpoint") {
    return fmt.Errorf("endpoint %q lacks %%d placeholder for sharding", endpoint)
}

Prevention

When it happens

Trigger: Calling NewSharded with an endpoint that contains no %d verb (e.g. 'http://shard.example.com' instead of 'http://shard%d.example.com'), or with extra arguments already baked in so Sprintf emits '%!(EXTRA int=0)'.

Common situations: Copy-pasting a normal single-endpoint config into the sharded storage type in JuiceFS's format/mount config; forgetting the %d placeholder when configuring sharded object storage.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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