skip to Main Content

I am getting errors with uploadthing and NextJS. The upload functionality worked before the version 14 and now doesn’t. I tried reverting to the previous version of NextJS 13 and now I’m getting console errors (Windows VSCode Terminal).

PS C:UsersHPDesktopDevelopmentKind Courseskind-courses> npm i
npm WARN ERESOLVE overriding peer dependency
npm WARN While resolving: [email protected]
npm WARN Found: [email protected]
npm WARN node_modules/next
npm WARN   next@"^13.4.12" from the root project
npm WARN   2 more (@clerk/nextjs, @uploadthing/react)
npm WARN
npm WARN Could not resolve dependency:
npm WARN peerOptional next@"14.0.1" from @uploadthing/[email protected]
npm WARN node_modules/@uploadthing/react
npm WARN   @uploadthing/react@"^6.0.1" from the root project
npm ERR! code ECONNRESET
npm ERR! errno ECONNRESET
npm ERR! network Invalid response body while trying to fetch https://registry.npmjs.org/@next%2fenv: aborted
npm ERR! network This is a problem related to network connectivity.        
npm ERR! network In most cases you are behind a proxy or have bad network settings.
npm ERR! network
npm ERR! network If you are behind a proxy, please make sure that the
npm ERR! network 'proxy' config is set properly.  See: 'npm help config'   

npm ERR! A complete log of this run can be found in: C:UsersHPAppDataLocalnpm-cache_logs2023-11-25T23_37_06_402Z-debug-0.log

At this point I wanted to try something else, like the native file upload but as a complete beginner on Nextjs and React and TypeScript, I have no clue where to start. I followed the whole documentation and did things right (I know this because the functionality worked). I also noticed that uploadthing gets UPDATED almost everyday and I think that’s why the functionality is working.

In my app/api/uploadthing/core.ts

import { createUploadthing, type FileRouter } from "uploadthing/next";
 
const f = createUploadthing();
 
const auth = (req: Request) => ({ id: "fakeId" }); // Fake auth function
 
// FileRouter for your app, can contain multiple FileRoutes
export const ourFileRouter = {
  // Define as many FileRoutes as you like, each with a unique routeSlug
  imageUploader: f({ image: { maxFileSize: "4MB" } })
    // Set permissions and file types for this FileRoute
    .middleware(async ({ req }) => {
      // This code runs on your server before upload
      const user = await auth(req);
 
      // If you throw, the user will not be able to upload
      if (!user) throw new Error("Unauthorized");
 
      // Whatever is returned here is accessible in onUploadComplete as `metadata`
      return { userId: user.id };
    })
    .onUploadComplete(async ({ metadata, file }) => {
      // This code RUNS ON YOUR SERVER after upload
      console.log("Upload complete for userId:", metadata.userId);
 
      console.log("file url", file.url);
 
      // !!! Whatever is returned here is sent to the clientside `onClientUploadComplete` callback
      return { uploadedBy: metadata.userId };
    }),
} satisfies FileRouter;
 
export type OurFileRouter = typeof ourFileRouter;

app/api/uploadthing/route.ts

import { createNextRouteHandler } from "uploadthing/next";
 
import { ourFileRouter } from "./core";
 
// Export routes for Next App Router
export const { GET, POST } = createNextRouteHandler({
  router: ourFileRouter,
});

tailwind.config.ts

import { withUt } from "uploadthing/tw";
 
export default withUt({
  // Your existing Tailwind config
  content: ["./src/**/*.{ts,tsx,mdx}"],
  ...
});

app/(dashboard)/(routes)/teacher/courses/[courseId]/_components/image-form.tsx

"use client"

import * as z from "zod";
import axios from "axios";
import { ImageIcon, Pencil, PlusCircle } from "lucide-react";
import { useState } from "react";
import toast from "react-hot-toast";
import { useRouter } from "next/navigation";
import Image from 'next/image'

import { Button } from "@/components/ui/button";
import { Class } from "@prisma/client";
import { FileUpload } from "@/components/file-upload";


interface ImageFormProps {
    initialData: Class;
    courseId: string;//or class
};

const formShema = z.object({
    imageUrl: z.string().min(1, ({
        message: "Image is required",
    }))
})

export const ImageForm = ({
    initialData,
    courseId,
}: ImageFormProps) => {
    const [isEditing, setIsEditing] = useState(false);


    const toggleEdit = () => {
        setIsEditing((current) => !current);
    }

    const router = useRouter();

    const onSubmit = async (values: z.infer<typeof formShema>) => {
        console.log("Form Values:", values);
        try {
            await axios.patch(`/api/courses/${courseId}`, values);
            toast.success("Class Updated");
            toggleEdit();
            router.refresh();
        } catch {
            toast.error("Something went wrong");
        }
    }

    return(
        <div className="mt-6 border bg-slate-100 rounded-md p-4">
            <div className="font-medium flex items-center justify-between">
                Class Image
                <Button onClick={toggleEdit} variant="ghost">
                    { isEditing && (
                        <>Cancel</>
                    )}
                    {!isEditing && !initialData.imageUrl && (
                        <>
                            <PlusCircle className="h-4 w-4 mr-2" />
                            Add Image
                        </>
                    )}
                    {
                        !isEditing && initialData.imageUrl && (
                            <>
                                <Pencil className="h-4 w-4 mr-2 "/>
                                Edit Image
                            </>
                        )
                    }
                </Button>
            </div>
            {!isEditing && (
                !initialData.imageUrl ? (
                    <div className="flex items-center justify-center h-60 bg-slate-200 rounded-md">
                        <ImageIcon className="h-10 w-10 text-slate-500"/>
                    </div>
                ) : (
                    <div className="relative aspect-video mt-2">
                        <Image alt="Upload" fill className="object-cover rounded-md" src={initialData.imageUrl }/>
                    </div>
                )
            )}
            {isEditing && (
                <div>
                    <FileUpload 
                        endpoint="courseImage"//or classImage
                        onChange={(url) => {
                            if(url){
                                onSubmit({ imageUrl: url})
                            }
                        }}
                    />
                    <div className="text-xs text-muted-foreground mt-4">
                        16:9 aspect ratio recomended

                    </div>
                </div>
            )}
        </div>
    )
}

And I’m also encountering this when I run the app and try to upload a file.

✓ Compiled /api/uploadthing/route in 1218ms (899 modules)
 ○ Compiling /not-found ...
 ✓ Compiled /not-found in 3.8s (1468 modules)
[UT] UploadThing dev server is now running!
[UT] UploadThing dev server is now running!
[UT] SIMULATING FILE UPLOAD WEBHOOK CALLBACK http://localhost:3000/api/uploadthing?slug=courseImage
INFO: Clerk: The request to /api/uploadthing is being protected (401) because there is no signed-in user, and the path is included in `apiRoutes`. To 
prevent this behavior, choose one of:

1. To prevent Clerk authentication from protecting (401) the api route, remove the rule matching "/api/uploadthing" from the `apiRoutes` array passed 
to authMiddleware
2. To make the route accessible to both signed in and signed out users, pass `publicRoutes: ["/api/uploadthing"]` to authMiddleware
3. To prevent Clerk authentication from running at all, pass `ignoredRoutes: ["/((?!api|trpc))(_next.*|.+.[w]+$)", "/api/uploadthing"]` to authMiddleware
4. Pass a custom `afterAuth` to authMiddleware, and replace Clerk's default behavior of redirecting unless a route is included in publicRoutes        

For additional information about middleware, please visit https://clerk.com/docs/nextjs/middleware
(This log only appears in development mode, or if `debug: true` is passed to authMiddleware)
[UT] Failed to simulate callback for file. Is your webhook configured correctly? 93f6b985-5279-4803-992c-416dcf7614f9-6s0ujg.png

2

Answers


  1. The 6.0.3 Uploadthing version resolve the error for me. She’s released 4 days ago.

    Login or Signup to reply.
  2. you can bypass this by making your route public in authMiddleware() , go to ur root directory if u are using app then seach for middleware.ts

    import { authMiddleware } from "@clerk/nextjs";
     
    // This example protects all routes including api/trpc routes
    // Please edit this to allow other routes to be public as needed.
    // See https://clerk.com/docs/references/nextjs/auth-middleware for more information about configuring your Middleware
    export default authMiddleware({ 
      publicRoutes:["/api/uploadthing"]
    });
     
    export const config = {
      matcher: ['/((?!.+\.[\w]+$|_next).*)', '/', '/(api|trpc)(.*)'],
    
    };
     
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search