Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/barcode8/VideoHub/llms.txt

Use this file to discover all available pages before exploring further.

All errors returned by the VideoHub API follow a consistent JSON envelope based on the ApiError class. Whether the problem is a missing field, an expired token, or an internal server fault, the response always has the same shape — making errors straightforward to handle in any client.

Error Response Shape

When a request fails, the API responds with a JSON body that mirrors the success envelope but with success set to false and data set to null. The errors array is populated when additional validation detail is available.
{
  "statusCode": 400,
  "data": null,
  "message": "All fields are required",
  "success": false,
  "errors": []
}
FieldTypeDescription
statusCodenumberMirrors the HTTP status code of the response
messagestringHuman-readable explanation of what went wrong
successbooleanAlways false for error responses
errorsarrayAdditional validation details; empty array when not applicable
Check the message field in error responses for human-readable detail. The errors array contains additional validation details when present.

HTTP Status Codes

VideoHub uses standard HTTP status codes. The table below lists every code you may encounter and its typical cause.
StatusMeaningCommon Trigger
200OKSuccessful read or update operation
201CreatedSuccessful resource creation (registration, video upload)
400Bad RequestMissing or invalid request fields
401UnauthorizedMissing, expired, or invalid JWT access token
403ForbiddenAuthenticated but not the owner or otherwise not permitted
404Not FoundRequested resource does not exist
409ConflictDuplicate resource (username, email, or playlist name already taken)
500Internal Server ErrorUpload failure, database error, or token generation failure

Error Handling Pattern

Every controller in VideoHub is wrapped with the asyncHandler utility. Any thrown ApiError — or any unexpected promise rejection — is caught by the try/catch wrapper, which immediately writes a JSON error response directly to res rather than delegating to a downstream error handler. This guarantees no unhandled rejection can crash the server.
const asyncHandler = (func) => async (req, res, next) => {
  try {
    return await func(req, res, next)
  } catch (error) {
    return res.status(error.statusCode || 500).json({
      success: false,
      message: error.message
    })
  }
}
When error.statusCode is not set (i.e. the error was not an ApiError instance), the handler falls back to 500 so the client always receives a well-formed response rather than an empty connection drop.

ApiError Constructor

Errors are created throughout the codebase using the ApiError class, which extends the native Error. Construct one anywhere you need to signal a failure:
new ApiError(statusCode, message, errors, stack)
ParameterTypeDefaultDescription
statusCodenumberHTTP status code to send to the client
messagestring"Something went wrong"Human-readable error description
errorsarray[]Optional array of additional validation detail objects
stackstring""Optional custom stack trace; if omitted, Error.captureStackTrace generates one automatically
The constructor sets this.success = false and this.data = null unconditionally, so the error shape is always consistent with the success envelope.

Authentication Errors

The verifyJwt middleware guards protected routes. The exact message you receive depends on what is wrong with the token.
StatusMessageCause
401"Please login first to perform this action"No token found in the Authorization header or accessToken cookie
401"Invalid access token"Token was valid JWT but the user ID it encodes no longer exists
401"Invalid or expired access token"jwt.verify threw — the token is expired, malformed, or signed with a different secret
401"Invalid Refresh Token"The refresh token used on /users/refresh-token is not valid or has been revoked
401"Unauthorized request"General authorization rejection from a protected route
Access tokens are short-lived. When you receive a 401 with "Invalid or expired access token", call the token refresh endpoint before retrying the original request. If the refresh token is also rejected, the user must log in again.

Validation Errors (400)

These 400 Bad Request responses are returned when required fields are absent, IDs are malformed, or input fails a logical check. Common messages across controllers
MessageSource
"All fields are required"User registration — username, email, fullname, or password missing
"Title is required"Video upload — title field not provided
"Video files are required"Video upload — no video file attached
"Comment body is mandatory"Comment creation — empty comment text
"Comment Id not received"Comment update/delete — no comment ID in params
"Video ID not recieved"Video operations — no video ID in request
"Playlist ID not recieved"Playlist operations — no playlist ID provided
"Playlist name is required"Playlist creation — name field is empty
"Playlist name cannot be empty"Playlist update — name set to blank string
"Please provide a name or description to update"Playlist update — neither field supplied
"This video is already in the playlist"Playlist — duplicate video add attempt
"User cannot subscribe to their own channel"Subscription — self-subscription attempt
"Invalid Video ID format"Any video route — ID fails MongoDB ObjectId validation
"Invalid Comment ID format"Any comment route — ID fails MongoDB ObjectId validation
"Invalid playlist ID"Any playlist route — ID fails MongoDB ObjectId validation
"Username or email is required"Login — both identifier fields are empty
"User does not exist"Login or profile — no matching account found
"You do not have permission to edit this comment"Comment update — comment was created by a different user
"You do not have permission to delete this comment"Comment delete — comment was created by a different user

Ownership / Permission Errors (403)

A 403 Forbidden response is returned when the authenticated user is valid but is not permitted to take the requested action on a resource they do not own.
MessageTrigger
"You do not have permission to modify this playlist"Trying to add/remove videos from another user’s playlist
"You do not have permission to toggle this video's status"Trying to publish/unpublish a video you did not upload
The API distinguishes between 401 Unauthorized (the request carries no valid identity) and 403 Forbidden (the identity is valid but lacks the required ownership). Always check the status code first when diagnosing access failures.

Not Found Errors (404)

MessageTrigger
"Video not found"The video ID is a valid ObjectId but no matching document exists
"Playlist not found"The playlist ID is valid but the playlist has been deleted or never existed
"Channel does not exist"Profile lookup for a username that has no account
"Playlist not found or you don't have permission to delete it"Delete attempted on a non-existent playlist or one owned by another user

Conflict Errors (409)

MessageTrigger
"User with email or username already exists"Registration — email or username is already taken
"Playlist with the same name already exists in your account"Playlist creation — the authenticated user already owns a playlist with that name

Internal Server Errors (500)

MessageTrigger
"Something went wrong while registering user"Database write failure during user creation
"Something went wrong while generating refresh and access token"JWT signing or database failure during token generation
"Error while uploading an avatar"Cloudinary upload for the avatar file failed
"Error while uploading the thumbnail"Cloudinary upload for the video thumbnail failed
"Failed to delete associated files from cloud storage"Cloudinary deletion during video removal failed

Build docs developers (and LLMs) love