{"record":{"id":"765801878ffa685a","repo":"AlistGo/alist","slug":"can-t-convert-obj-to-url-765801","errorCode":null,"errorMessage":"can't convert obj to URL","messagePattern":"can't convert obj to URL","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/teambition/driver.go","lineNumber":50,"sourceCode":"\nfunc (d *Teambition) Drop(ctx context.Context) error {\n\treturn nil\n}\n\nfunc (d *Teambition) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {\n\treturn d.getFiles(dir.GetID())\n}\n\nfunc (d *Teambition) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {\n\tif u, ok := file.(model.URL); ok {\n\t\turl := u.URL()\n\t\tres, _ := base.NoRedirectClient.R().Get(url)\n\t\tif res.StatusCode() == 302 {\n\t\t\turl = res.Header().Get(\"location\")\n\t\t}\n\t\treturn &model.Link{URL: url}, nil\n\t}\n\treturn nil, errors.New(\"can't convert obj to URL\")\n}\n\nfunc (d *Teambition) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {\n\tdata := base.Json{\n\t\t\"objectType\":     \"collection\",\n\t\t\"_projectId\":     d.ProjectID,\n\t\t\"_creatorId\":     \"\",\n\t\t\"created\":        \"\",\n\t\t\"updated\":        \"\",\n\t\t\"title\":          dirName,\n\t\t\"color\":          \"blue\",\n\t\t\"description\":    \"\",\n\t\t\"workCount\":      0,\n\t\t\"collectionType\": \"\",\n\t\t\"recentWorks\":    []interface{}{},\n\t\t\"_parentId\":      parentDir.GetID(),\n\t\t\"subCount\":       nil,\n\t}","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/teambition/driver.go#L32-L68","documentation":"Teambition's Link() only supports objects that implement model.URL (objects that already carry a direct download URL). It does a Go interface type assertion file.(model.URL); if the obj is a plain model.Object without a URL method, the assertion fails and Link returns this error instead of a link. There is no fallback API call to fetch a URL on demand.","triggerScenarios":"Calling Link() on a Teambition file object that was constructed as a generic model.Object rather than the driver's URL-carrying object type (e.g. from a cache layer that rebuilt objects, or a custom caller synthesizing objects).","commonSituations":"Metadata cache re-serializing objects and losing the original type; Custom integrations calling Link with objects from List() of a different driver; Driver versions where only some object kinds (uploaded files vs. collections) implement model.URL","solutions":["Pass the original object instance returned by getFiles()/List(), preserving its concrete type","Disable or clear the metadata cache for this storage if it is downcasting objects","Update the driver — newer versions attach URLs at List time so the assertion holds"],"exampleFix":"// before\nvar file model.Obj = &model.Object{Name: \"doc.pdf\"}\nlink, err := d.Link(ctx, file, args) // -> \"can't convert obj to URL\"\n\n// after\nfiles, _ := d.List(ctx, dir, model.ListArgs{})\nvar file model.Obj\nfor _, f := range files { if f.GetName() == \"doc.pdf\" { file = f } }\nlink, err := d.Link(ctx, file, args)","handlingStrategy":"type-guard","validationCode":"// before calling Link, ensure the object carries a URL\nif _, ok := file.(model.URL); !ok {\n    return fmt.Errorf(\"object %q cannot be linked directly; re-list to obtain a URL-capable object\", file.GetName())\n}","typeGuard":"func isURLCarrier(o model.Obj) bool {\n    _, ok := o.(model.URL)\n    return ok\n}","tryCatchPattern":"link, err := d.Link(ctx, file, args)\nif err != nil && strings.Contains(err.Error(), \"can't convert obj to URL\") {\n    objs, _ := d.List(ctx, parentDir, model.ListArgs{})\n    for _, o := range objs {\n        if o.GetName() == file.GetName() {\n            if _, ok := o.(model.URL); ok {\n                link, err = d.Link(ctx, o, args)\n            }\n        }\n    }\n}","preventionTips":["Never rebuild Teambition objects across serialization boundaries — pass originals","Check the type assertion before calling Link on uncertain objects","Keep driver and metadata cache versions in sync so URL-carrying types survive"],"tags":["teambition","type-assertion","link","interface"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}