Question
After upgrading an Angular application from Angular 4.4 to Angular 5.x, I replaced usages of HttpModule and Http with HttpClientModule and HttpClient. After that, the application started throwing this error:
Error: StaticInjectorError[HttpClient]:
StaticInjectorError[HttpClient]:
NullInjectorError: No provider for HttpClient!
In app.module.ts, HttpClientModule appears to be imported correctly:
import { HttpModule } from '@angular/http';
import { HttpClientModule, HttpClient } from '@angular/common/http';
@NgModule({
imports: [
BrowserModule,
HttpClientModule,
HttpModule,
BrowserAnimationsModule,
FormsModule,
AppRoutingModule
]
})
export class AppModule {}
I also added HttpModule again to make sure the issue was not caused by a missing dependency, but that did not solve the problem.
I am not sure where this error is coming from or how to trace it properly. I also see this warning during the build, and I am wondering whether it is related:
There are multiple modules with names that only differ in casing.
...
D:\XXX\node_modules\@angular\Common\esm5\http.js
D:\XXX\node_modules\@angular\common\esm5\http.js
Relevant environment details:
- Angular 5.0.0 / 5.0.1 / 5.1 beta
- Node 8.5.0
- Windows
- Custom Webpack setup
What causes Angular to report "No provider for HttpClient" even when HttpClientModule is imported, and how can it be fixed correctly?
Short Answer
By the end of this page, you will understand how Angular dependency injection provides HttpClient, why importing HttpClientModule in the correct module matters, and how build issues such as incorrect import casing can still cause the "No provider for HttpClient" error even when your code looks correct.
Concept
Angular uses dependency injection (DI) to create objects such as services. HttpClient is not something Angular creates automatically by magic. It becomes available only when Angular sees the provider setup from HttpClientModule.
When you write code like this:
constructor(private http: HttpClient) {}
Angular checks its injector and asks:
- Do I know how to create
HttpClient? - Was the module that provides it imported?
- Am I in the right injector scope?
If the answer is no, Angular throws:
NullInjectorError: No provider for HttpClient!
Why this matters
This is a core Angular concept, not just an HTTP issue. The same pattern applies to many Angular features:
- forms modules provide form directives
- router modules provide routing services
- HTTP modules provide
HttpClient - feature modules can have their own providers
So the real lesson is:
- Angular features often require module imports
- services are resolved through dependency injection
- wrong imports, wrong module scope, or duplicated builds can break DI
Mental Model
Think of Angular's injector as a tool cabinet.
HttpClientis a tool you want to use.HttpClientModuleis the instruction that tells Angular to put that tool in the cabinet.- Your component or service asks for the tool.
If the tool was never added to the cabinet, Angular says:
- No provider for HttpClient
Now imagine you accidentally label one shelf as common and another as Common. On some systems those may be treated differently. You may think the tool is in the cabinet, but Angular is looking in one shelf while the tool was registered in another. That is why inconsistent import casing can produce confusing dependency injection errors.
Syntax and Examples
The core syntax for using HttpClient is:
import { HttpClientModule } from '@angular/common/http';
import { HttpClient } from '@angular/common/http';
And in your root module:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, HttpClientModule],
bootstrap: [AppComponent]
})
export class AppModule {}
Then in a service:
Step by Step Execution
Consider this small example:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable()
export class ProductService {
constructor(private http: HttpClient) {}
}
And this module:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
imports: [BrowserModule]
})
export class AppModule {}
What happens step by step
- Angular starts the application with
AppModule. - Angular reads the
importsarray. - is registered.
Real World Use Cases
Dependency injection and module-provided services appear everywhere in Angular apps.
API services
Most applications wrap HttpClient in services:
this.http.get('/api/orders')
this.http.post('/api/login', credentials)
If HttpClientModule is missing, all API communication fails.
Feature modules
Large apps split code into modules such as:
AdminModuleUserModuleSharedModule
If services are declared and used across these modules, understanding where providers come from becomes essential.
Testing
In tests, developers often replace HttpClientModule with HttpClientTestingModule so requests can be mocked safely.
Migration work
When upgrading Angular versions, teams often move from old APIs to new ones. During migrations, mixed imports such as Http + are common sources of errors.
Real Codebase Usage
In real Angular codebases, developers usually handle this concept through a few common patterns.
1. Import framework modules only once in the correct place
Usually, root-level framework modules are imported in AppModule:
imports: [BrowserModule, HttpClientModule, AppRoutingModule]
This makes shared infrastructure available app-wide.
2. Keep HTTP logic inside services
Instead of making HTTP calls in components, developers write services:
@Injectable()
export class NotificationService {
constructor(private http: HttpClient) {}
load() {
return this.http.get('/api/notifications');
}
}
This keeps components simpler and easier to test.
3. Use guard clauses and validation around responses
A service might validate parameters before making requests:
() {
(!id) {
();
}
..();
}
Common Mistakes
1. Importing HttpModule but injecting HttpClient
Broken code:
import { HttpModule } from '@angular/http';
import { HttpClient } from '@angular/common/http';
Why it fails:
HttpModuleprovides the oldHttp- it does not provide
HttpClient
Fix:
import { HttpClientModule } from '@angular/common/http';
2. Importing HttpClientModule in the wrong module
If the app bootstraps AppModule but you imported HttpClientModule somewhere else that is never loaded, Angular still will not find the provider.
Fix:
- import it in the module that is actually used
Comparisons
| Concept | Old API | New API | When to use |
|---|---|---|---|
| Angular HTTP module | HttpModule from @angular/http | HttpClientModule from @angular/common/http | Use HttpClientModule in Angular 4.3+ |
| Injected service | Http | HttpClient | Prefer HttpClient |
| Response handling | Manual parsing often needed | JSON handling is more convenient | Prefer HttpClient |
| Provider source |
Cheat Sheet
// New Angular HTTP API
import { HttpClientModule } from '@angular/common/http';
import { HttpClient } from '@angular/common/http';
// Old Angular HTTP API
import { HttpModule } from '@angular/http';
import { Http } from '@angular/http';
Rules
- If you inject
HttpClient, importHttpClientModule HttpModuledoes not provideHttpClient- Use exact lowercase package paths like
@angular/common/http - Avoid mixing
HttpandHttpClientunless you are migrating carefully - In custom Webpack setups, rebuild vendor bundles after Angular upgrades
Quick fix checklist
- Check
AppModuleimports - Search project for
@angular/Commonor other wrong casing
FAQ
Why do I get "No provider for HttpClient" even though I imported HttpClientModule?
Usually because the module import is in the wrong place, the wrong module is being bootstrapped, or the build has duplicated Angular packages due to path or casing issues.
Does HttpModule provide HttpClient?
No. HttpModule provides the older Http service. HttpClient requires HttpClientModule.
Can incorrect import casing really cause Angular DI errors?
Yes. With some build tools, @angular/Common and @angular/common can be treated as different module paths, leading to duplicate module instances and missing providers.
Should I keep both HttpModule and HttpClientModule during migration?
Only temporarily if some code still uses the old Http service. But new code should use HttpClient, and old imports should be removed as migration finishes.
Should I add HttpClient to the providers array manually?
Mini Project
Description
Build a small Angular service setup that fetches data from an API using HttpClient. This project demonstrates the exact dependency injection chain required for HTTP requests and helps you practice the correct module import pattern that prevents the "No provider for HttpClient" error.
Goal
Create a working Angular service that uses HttpClient to load a list of users, with the correct HttpClientModule setup in the application module.
Requirements
- Import
HttpClientModulein the root Angular module. - Create a service that injects
HttpClient. - Add a method that fetches data from
/api/users. - Create a component that calls the service on initialization.
- Display the returned data or a loading message.
Keep learning
Related questions
Angular formGroup Error Explained: Fixing 'Can't bind to formGroup' in Reactive Forms
Learn why Angular shows 'Can't bind to formGroup' and how to fix it by importing ReactiveFormsModule correctly.
Fix "Element implicitly has an 'any' type" in TypeScript Object Indexing
Learn why TypeScript rejects string object indexing and how to fix it with keyof, unions, and typed object keys in React.
Fix "Property has no initializer" in Angular TypeScript Components
Learn why Angular TypeScript shows "Property has no initializer" and how to fix it using defaults, optional properties, or definite assignment.