From 987168b863c52d0548050ffbac569782bb9a8cef Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Sat, 13 Apr 2019 01:43:22 +0900
Subject: [PATCH] strictNullChecks (#4666)

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip
---
 gulpfile.ts                                   |   2 +-
 package.json                                  |   2 +-
 src/boot/master.ts                            |   2 +-
 src/boot/worker.ts                            |   2 +-
 src/config/load.ts                            |   2 +-
 src/daemons/notes-stats-child.ts              |   2 +-
 src/db/postgre.ts                             |   4 +-
 src/games/reversi/core.ts                     |  16 +--
 src/mfm/fromHtml.ts                           |   2 -
 src/mfm/parse.ts                              |   4 +-
 src/mfm/toHtml.ts                             |   2 +-
 src/misc/acct/type.ts                         |   2 +-
 src/misc/convert-host.ts                      |   3 +-
 src/misc/detect-mine.ts                       |   2 +-
 src/misc/donwload-url.ts                      |   3 +-
 src/misc/fetch-meta.ts                        |   1 -
 src/misc/fetch-proxy-account.ts               |   3 +-
 src/misc/identifiable-error.ts                |   2 +-
 src/misc/nyaize.ts                            |   4 +-
 src/misc/schema.ts                            |   4 +-
 src/models/entities/poll.ts                   |   2 +-
 src/models/repositories/abuse-user-report.ts  |   3 +-
 src/models/repositories/app.ts                |   3 +-
 src/models/repositories/auth-session.ts       |   3 +-
 src/models/repositories/blocking.ts           |   3 +-
 src/models/repositories/drive-file.ts         |   5 +-
 src/models/repositories/drive-folder.ts       |   3 +-
 src/models/repositories/follow-request.ts     |   3 +-
 src/models/repositories/following.ts          |  43 +++++-
 src/models/repositories/games/reversi/game.ts |   3 +-
 .../repositories/games/reversi/matching.ts    |   3 +-
 src/models/repositories/messaging-message.ts  |   3 +-
 src/models/repositories/muting.ts             |   3 +-
 src/models/repositories/note-favorite.ts      |   3 +-
 src/models/repositories/note-reaction.ts      |   3 +-
 src/models/repositories/note.ts               |  17 +--
 src/models/repositories/notification.ts       |  15 ++-
 src/models/repositories/user-list.ts          |   5 +-
 src/models/repositories/user.ts               |  29 ++--
 src/prelude/ensure.ts                         |   7 +
 src/queue/index.ts                            |   4 +-
 src/queue/processors/db/delete-drive-files.ts |   8 +-
 src/queue/processors/db/export-blocking.ts    |  12 +-
 src/queue/processors/db/export-following.ts   |  12 +-
 src/queue/processors/db/export-mute.ts        |  12 +-
 src/queue/processors/db/export-notes.ts       |  15 ++-
 src/queue/processors/db/export-user-lists.ts  |   8 +-
 src/queue/processors/db/import-following.ts   |  16 ++-
 src/queue/processors/db/import-user-lists.ts  |  22 +--
 src/queue/processors/deliver.ts               |   2 +-
 src/queue/processors/inbox.ts                 |   9 +-
 .../activitypub/kernel/accept/follow.ts       |   3 +-
 src/remote/activitypub/kernel/add/index.ts    |   1 +
 .../activitypub/kernel/announce/note.ts       |   9 +-
 src/remote/activitypub/kernel/block/index.ts  |   3 +-
 src/remote/activitypub/kernel/follow.ts       |   3 +-
 src/remote/activitypub/kernel/index.ts        |   2 +-
 src/remote/activitypub/kernel/like.ts         |   1 +
 .../activitypub/kernel/reject/follow.ts       |   3 +-
 src/remote/activitypub/kernel/remove/index.ts |   1 +
 src/remote/activitypub/kernel/undo/block.ts   |   3 +-
 src/remote/activitypub/kernel/undo/follow.ts  |   3 +-
 src/remote/activitypub/kernel/undo/index.ts   |   2 -
 src/remote/activitypub/kernel/undo/like.ts    |   1 +
 src/remote/activitypub/models/image.ts        |  17 +--
 src/remote/activitypub/models/note.ts         | 126 ++++++++++--------
 src/remote/activitypub/models/person.ts       |  81 +++++------
 src/remote/activitypub/models/question.ts     |   8 +-
 src/remote/activitypub/models/tag.ts          |   8 +-
 src/remote/activitypub/renderer/block.ts      |   2 +-
 .../activitypub/renderer/follow-user.ts       |   3 +-
 src/remote/activitypub/renderer/note.ts       |  19 ++-
 .../renderer/ordered-collection-page.ts       |   2 +-
 src/remote/activitypub/renderer/person.ts     |  15 +--
 src/remote/activitypub/request.ts             |   9 +-
 src/remote/resolve-user.ts                    |  31 ++++-
 src/remote/webfinger.ts                       |   2 +-
 src/server/activitypub.ts                     |  13 +-
 src/server/activitypub/featured.ts            |   6 +-
 src/server/activitypub/followers.ts           |   6 +-
 src/server/activitypub/following.ts           |   6 +-
 src/server/activitypub/outbox.ts              |   9 +-
 src/server/api/api-handler.ts                 |  14 +-
 src/server/api/authenticate.ts                |   2 +-
 src/server/api/call.ts                        |  10 +-
 .../api/common/make-pagination-query.ts       |   2 +-
 src/server/api/define.ts                      |  10 +-
 .../api/endpoints/admin/abuse-user-reports.ts |   2 +-
 src/server/api/endpoints/admin/drive/files.ts |   4 +-
 src/server/api/endpoints/admin/emoji/list.ts  |   2 +-
 .../admin/federation/remove-all-following.ts  |   7 +-
 src/server/api/endpoints/admin/logs.ts        |   2 +-
 src/server/api/endpoints/admin/queue/jobs.ts  |   4 +-
 src/server/api/endpoints/admin/show-users.ts  |   2 +-
 .../api/endpoints/admin/update-remote-user.ts |   2 +-
 src/server/api/endpoints/ap/show.ts           |   4 +-
 src/server/api/endpoints/auth/accept.ts       |   3 +-
 .../api/endpoints/auth/session/userkey.ts     |   3 +-
 src/server/api/endpoints/blocking/list.ts     |   2 +-
 .../api/endpoints/charts/active-users.ts      |   2 +-
 src/server/api/endpoints/charts/drive.ts      |   2 +-
 src/server/api/endpoints/charts/federation.ts |   2 +-
 src/server/api/endpoints/charts/hashtag.ts    |   2 +-
 src/server/api/endpoints/charts/instance.ts   |   2 +-
 src/server/api/endpoints/charts/network.ts    |   2 +-
 src/server/api/endpoints/charts/notes.ts      |   2 +-
 src/server/api/endpoints/charts/user/drive.ts |   2 +-
 .../api/endpoints/charts/user/following.ts    |   2 +-
 src/server/api/endpoints/charts/user/notes.ts |   2 +-
 .../api/endpoints/charts/user/reactions.ts    |   2 +-
 src/server/api/endpoints/charts/users.ts      |   2 +-
 src/server/api/endpoints/drive/files.ts       |   2 +-
 .../api/endpoints/drive/files/create.ts       |   2 +-
 src/server/api/endpoints/drive/files/show.ts  |  10 +-
 src/server/api/endpoints/drive/folders.ts     |   2 +-
 .../api/endpoints/drive/folders/update.ts     |   6 +-
 src/server/api/endpoints/drive/stream.ts      |   2 +-
 .../api/endpoints/federation/instances.ts     |   2 +-
 .../api/endpoints/games/reversi/games.ts      |   2 +-
 .../api/endpoints/games/reversi/match.ts      |   4 +-
 src/server/api/endpoints/hashtags/list.ts     |   2 +-
 src/server/api/endpoints/hashtags/search.ts   |   2 +-
 src/server/api/endpoints/hashtags/users.ts    |   2 +-
 src/server/api/endpoints/i/2fa/done.ts        |   3 +-
 src/server/api/endpoints/i/2fa/register.ts    |   5 +-
 src/server/api/endpoints/i/2fa/unregister.ts  |   5 +-
 src/server/api/endpoints/i/authorized-apps.ts |   2 +-
 src/server/api/endpoints/i/change-password.ts |   5 +-
 src/server/api/endpoints/i/delete-account.ts  |   5 +-
 src/server/api/endpoints/i/favorites.ts       |   2 +-
 src/server/api/endpoints/i/notifications.ts   |   6 +-
 .../api/endpoints/i/regenerate-token.ts       |   5 +-
 src/server/api/endpoints/i/signin-history.ts  |   2 +-
 src/server/api/endpoints/i/update-email.ts    |   5 +-
 src/server/api/endpoints/i/update.ts          |   6 +-
 src/server/api/endpoints/messaging/history.ts |   2 +-
 src/server/api/endpoints/mute/list.ts         |   2 +-
 src/server/api/endpoints/my/apps.ts           |   2 +-
 src/server/api/endpoints/notes.ts             |   2 +-
 src/server/api/endpoints/notes/children.ts    |   2 +-
 .../api/endpoints/notes/conversation.ts       |   5 +-
 src/server/api/endpoints/notes/create.ts      |  27 ++--
 src/server/api/endpoints/notes/delete.ts      |   3 +-
 src/server/api/endpoints/notes/featured.ts    |   2 +-
 .../api/endpoints/notes/global-timeline.ts    |   2 +-
 .../api/endpoints/notes/hybrid-timeline.ts    |   2 +-
 .../api/endpoints/notes/local-timeline.ts     |   8 +-
 src/server/api/endpoints/notes/mentions.ts    |   2 +-
 .../endpoints/notes/polls/recommendation.ts   |   2 +-
 src/server/api/endpoints/notes/polls/vote.ts  |   7 +-
 src/server/api/endpoints/notes/reactions.ts   |   2 +-
 src/server/api/endpoints/notes/renotes.ts     |   2 +-
 src/server/api/endpoints/notes/replies.ts     |   2 +-
 .../api/endpoints/notes/search-by-tag.ts      |   4 +-
 src/server/api/endpoints/notes/search.ts      |   2 +-
 src/server/api/endpoints/notes/timeline.ts    |   2 +-
 .../api/endpoints/notes/user-list-timeline.ts |   2 +-
 src/server/api/endpoints/users.ts             |   2 +-
 src/server/api/endpoints/users/followers.ts   |   4 +-
 src/server/api/endpoints/users/following.ts   |   4 +-
 .../users/get-frequently-replied-users.ts     |   2 +-
 src/server/api/endpoints/users/notes.ts       |   8 +-
 .../api/endpoints/users/recommendation.ts     |   2 +-
 src/server/api/endpoints/users/search.ts      |   6 +-
 src/server/api/endpoints/users/show.ts        |   6 +-
 src/server/api/error.ts                       |   4 +-
 src/server/api/limiter.ts                     |   6 +-
 src/server/api/private/signin.ts              |   5 +-
 src/server/api/private/signup.ts              |   4 +-
 src/server/api/service/discord.ts             |  91 +++++++------
 src/server/api/service/github.ts              |  45 ++++---
 src/server/api/service/twitter.ts             |  25 ++--
 src/server/api/stream/channels/admin.ts       |   2 +-
 src/server/api/stream/channels/drive.ts       |   2 +-
 .../api/stream/channels/games/reversi-game.ts |  80 ++++++-----
 .../api/stream/channels/games/reversi.ts      |   4 +-
 .../api/stream/channels/home-timeline.ts      |   8 +-
 .../api/stream/channels/hybrid-timeline.ts    |  10 +-
 src/server/api/stream/channels/main.ts        |   4 +-
 .../api/stream/channels/messaging-index.ts    |   2 +-
 src/server/api/stream/channels/messaging.ts   |   4 +-
 src/server/api/stream/index.ts                |  20 +--
 src/server/file/send-drive-file.ts            |   2 +-
 src/server/index.ts                           |   2 +-
 src/server/web/docs.ts                        |   6 +-
 src/server/web/feed.ts                        |   9 +-
 src/server/web/index.ts                       |   5 +-
 src/server/web/url-preview.ts                 |   2 +-
 src/server/well-known.ts                      |   4 +-
 src/services/blocking/create.ts               |   2 +-
 src/services/chart/core.ts                    |  36 ++---
 src/services/create-notification.ts           |   1 +
 src/services/drive/add-file.ts                |  36 ++---
 src/services/drive/delete-file.ts             |  16 +--
 src/services/drive/image-processor.ts         |   2 +-
 src/services/drive/upload-from-url.ts         |  11 +-
 src/services/following/create.ts              |   3 +-
 src/services/following/requests/accept-all.ts |   3 +-
 src/services/following/requests/accept.ts     |   2 +-
 src/services/following/requests/reject.ts     |   2 +-
 src/services/i/pin.ts                         |  15 +--
 src/services/i/update.ts                      |   7 +-
 src/services/logger.ts                        |  16 +--
 src/services/note/create.ts                   | 101 +++++++-------
 src/services/note/polls/update.ts             |  11 +-
 src/services/note/polls/vote.ts               |  16 +--
 src/services/note/reaction/create.ts          |   4 +-
 src/services/note/reaction/delete.ts          |   2 +-
 src/services/push-notification.ts             |  25 ++--
 .../register-or-fetch-instance-doc.ts         |   2 -
 src/services/stream.ts                        |   6 +-
 src/tools/clean-remote-files.ts               |   3 +-
 src/tools/show-signin-history.ts              |   4 +-
 tsconfig.json                                 |   3 +-
 214 files changed, 939 insertions(+), 785 deletions(-)
 create mode 100644 src/prelude/ensure.ts

diff --git a/gulpfile.ts b/gulpfile.ts
index b2956c2403..2242843db1 100644
--- a/gulpfile.ts
+++ b/gulpfile.ts
@@ -120,7 +120,7 @@ gulp.task('copy:client', () =>
 		])
 			.pipe(isProduction ? (imagemin as any)() : gutil.noop())
 			.pipe(rename(path => {
-				path.dirname = path.dirname.replace('assets', '.');
+				path.dirname = path.dirname!.replace('assets', '.');
 			}))
 			.pipe(gulp.dest('./built/client/assets/'))
 );
diff --git a/package.json b/package.json
index e89f98043c..e08a49462d 100644
--- a/package.json
+++ b/package.json
@@ -106,7 +106,7 @@
 		"bcryptjs": "2.4.3",
 		"bootstrap-vue": "2.0.0-rc.13",
 		"bull": "3.7.0",
-		"cafy": "15.1.0",
+		"cafy": "15.1.1",
 		"chai": "4.2.0",
 		"chai-http": "4.2.1",
 		"chalk": "2.4.2",
diff --git a/src/boot/master.ts b/src/boot/master.ts
index 2d4080fdb0..4d360c7265 100644
--- a/src/boot/master.ts
+++ b/src/boot/master.ts
@@ -44,7 +44,7 @@ function greet() {
 export async function masterMain() {
 	greet();
 
-	let config: Config;
+	let config!: Config;
 
 	try {
 		// initialize app
diff --git a/src/boot/worker.ts b/src/boot/worker.ts
index ca3716972a..362fa3f26b 100644
--- a/src/boot/worker.ts
+++ b/src/boot/worker.ts
@@ -15,6 +15,6 @@ export async function workerMain() {
 
 	if (cluster.isWorker) {
 		// Send a 'ready' message to parent process
-		process.send('ready');
+		process.send!('ready');
 	}
 }
diff --git a/src/config/load.ts b/src/config/load.ts
index 6200faf12a..26b25eab4e 100644
--- a/src/config/load.ts
+++ b/src/config/load.ts
@@ -29,7 +29,7 @@ export default function load() {
 
 	config.url = url.origin;
 
-	config.port = config.port || parseInt(process.env.PORT, 10);
+	config.port = config.port || parseInt(process.env.PORT || '', 10);
 
 	mixin.host = url.host;
 	mixin.hostname = url.hostname;
diff --git a/src/daemons/notes-stats-child.ts b/src/daemons/notes-stats-child.ts
index c491aed4cd..b60f5badfd 100644
--- a/src/daemons/notes-stats-child.ts
+++ b/src/daemons/notes-stats-child.ts
@@ -19,7 +19,7 @@ initDb().then(() => {
 			all, local
 		};
 
-		process.send(stats);
+		process.send!(stats);
 	}
 
 	tick();
diff --git a/src/db/postgre.ts b/src/db/postgre.ts
index e5726e9c87..641a552c09 100644
--- a/src/db/postgre.ts
+++ b/src/db/postgre.ts
@@ -76,7 +76,7 @@ class MyCustomLogger implements Logger {
 }
 
 export function initDb(justBorrow = false, sync = false, log = false) {
-	const enableLogging = log || !['production', 'test'].includes(process.env.NODE_ENV);
+	const enableLogging = log || !['production', 'test'].includes(process.env.NODE_ENV || '');
 
 	try {
 		const conn = getConnection();
@@ -93,7 +93,7 @@ export function initDb(justBorrow = false, sync = false, log = false) {
 		synchronize: process.env.NODE_ENV === 'test' || sync,
 		dropSchema: process.env.NODE_ENV === 'test' && !justBorrow,
 		logging: enableLogging,
-		logger: enableLogging ? new MyCustomLogger() : null,
+		logger: enableLogging ? new MyCustomLogger() : undefined,
 		entities: [
 			Meta,
 			Instance,
diff --git a/src/games/reversi/core.ts b/src/games/reversi/core.ts
index bb27d6f803..cf8986263b 100644
--- a/src/games/reversi/core.ts
+++ b/src/games/reversi/core.ts
@@ -37,7 +37,7 @@ export type Undo = {
 	/**
 	 * ターン
 	 */
-	turn: Color;
+	turn: Color | null;
 };
 
 /**
@@ -47,12 +47,12 @@ export default class Reversi {
 	public map: MapPixel[];
 	public mapWidth: number;
 	public mapHeight: number;
-	public board: Color[];
-	public turn: Color = BLACK;
+	public board: (Color | null | undefined)[];
+	public turn: Color | null = BLACK;
 	public opts: Options;
 
 	public prevPos = -1;
-	public prevColor: Color = null;
+	public prevColor: Color | null = null;
 
 	private logs: Undo[] = [];
 
@@ -145,12 +145,12 @@ export default class Reversi {
 		// ターン計算
 		this.turn =
 			this.canPutSomewhere(!this.prevColor) ? !this.prevColor :
-			this.canPutSomewhere(this.prevColor) ? this.prevColor :
+			this.canPutSomewhere(this.prevColor!) ? this.prevColor :
 			null;
 	}
 
 	public undo() {
-		const undo = this.logs.pop();
+		const undo = this.logs.pop()!;
 		this.prevColor = undo.color;
 		this.prevPos = undo.pos;
 		this.board[undo.pos] = null;
@@ -254,10 +254,10 @@ export default class Reversi {
 	/**
 	 * ゲームの勝者 (null = 引き分け)
 	 */
-	public get winner(): Color {
+	public get winner(): Color | null {
 		return this.isEnded ?
 			this.blackCount == this.whiteCount ? null :
 			this.opts.isLlotheo === this.blackCount > this.whiteCount ? WHITE : BLACK :
-			undefined;
+			undefined as never;
 	}
 }
diff --git a/src/mfm/fromHtml.ts b/src/mfm/fromHtml.ts
index 369f9de0ee..5fc4a16416 100644
--- a/src/mfm/fromHtml.ts
+++ b/src/mfm/fromHtml.ts
@@ -3,8 +3,6 @@ import { URL } from 'url';
 import { urlRegex } from './prelude';
 
 export function fromHtml(html: string): string {
-	if (html == null) return null;
-
 	const dom = parseFragment(html) as DefaultTreeDocumentFragment;
 
 	let text = '';
diff --git a/src/mfm/parse.ts b/src/mfm/parse.ts
index 9d60771708..f8464121f3 100644
--- a/src/mfm/parse.ts
+++ b/src/mfm/parse.ts
@@ -2,7 +2,7 @@ import { mfmLanguage } from './language';
 import { MfmForest } from './prelude';
 import { normalize } from './normalize';
 
-export function parse(source: string): MfmForest {
+export function parse(source: string | null): MfmForest | null {
 	if (source == null || source == '') {
 		return null;
 	}
@@ -10,7 +10,7 @@ export function parse(source: string): MfmForest {
 	return normalize(mfmLanguage.root.tryParse(source));
 }
 
-export function parsePlain(source: string): MfmForest {
+export function parsePlain(source: string | null): MfmForest | null {
 	if (source == null || source == '') {
 		return null;
 	}
diff --git a/src/mfm/toHtml.ts b/src/mfm/toHtml.ts
index 3cd7987624..58976fc2c3 100644
--- a/src/mfm/toHtml.ts
+++ b/src/mfm/toHtml.ts
@@ -4,7 +4,7 @@ import { intersperse } from '../prelude/array';
 import { MfmForest, MfmTree } from './prelude';
 import { IMentionedRemoteUsers } from '../models/entities/note';
 
-export function toHtml(tokens: MfmForest, mentionedRemoteUsers: IMentionedRemoteUsers = []) {
+export function toHtml(tokens: MfmForest | null, mentionedRemoteUsers: IMentionedRemoteUsers = []) {
 	if (tokens == null) {
 		return null;
 	}
diff --git a/src/misc/acct/type.ts b/src/misc/acct/type.ts
index c88a920c69..7f31257400 100644
--- a/src/misc/acct/type.ts
+++ b/src/misc/acct/type.ts
@@ -1,6 +1,6 @@
 type Acct = {
 	username: string;
-	host: string;
+	host: string | null;
 };
 
 export default Acct;
diff --git a/src/misc/convert-host.ts b/src/misc/convert-host.ts
index f7feebd55c..dbf7864550 100644
--- a/src/misc/convert-host.ts
+++ b/src/misc/convert-host.ts
@@ -2,7 +2,7 @@ import config from '../config';
 import { toASCII } from 'punycode';
 import { URL } from 'url';
 
-export function getFullApAccount(username: string, host: string) {
+export function getFullApAccount(username: string, host: string | null) {
 	return host ? `${username}@${toPuny(host)}` : `${username}@${toPuny(config.host)}`;
 }
 
@@ -17,6 +17,5 @@ export function extractDbHost(uri: string) {
 }
 
 export function toPuny(host: string) {
-	if (host == null) return null;
 	return toASCII(host.toLowerCase());
 }
diff --git a/src/misc/detect-mine.ts b/src/misc/detect-mine.ts
index bbf49efc10..70d58ffe21 100644
--- a/src/misc/detect-mine.ts
+++ b/src/misc/detect-mine.ts
@@ -3,7 +3,7 @@ import fileType from 'file-type';
 import checkSvg from '../misc/check-svg';
 
 export async function detectMine(path: string) {
-	return new Promise<[string, string]>((res, rej) => {
+	return new Promise<[string, string | null]>((res, rej) => {
 		const readable = fs.createReadStream(path);
 		readable
 			.on('error', rej)
diff --git a/src/misc/donwload-url.ts b/src/misc/donwload-url.ts
index 0dd4e4ef5d..167e01fdd1 100644
--- a/src/misc/donwload-url.ts
+++ b/src/misc/donwload-url.ts
@@ -1,5 +1,4 @@
 import * as fs from 'fs';
-import * as URL from 'url';
 import * as request from 'request';
 import config from '../config';
 import chalk from 'chalk';
@@ -26,7 +25,7 @@ export async function downloadUrl(url: string, path: string) {
 			rej(error);
 		});
 
-		const requestUrl = URL.parse(url).pathname.match(/[^\u0021-\u00ff]/) ? encodeURI(url) : url;
+		const requestUrl = new URL(url).pathname.match(/[^\u0021-\u00ff]/) ? encodeURI(url) : url;
 
 		const req = request({
 			url: requestUrl,
diff --git a/src/misc/fetch-meta.ts b/src/misc/fetch-meta.ts
index d1483e9edb..cf1fc474ce 100644
--- a/src/misc/fetch-meta.ts
+++ b/src/misc/fetch-meta.ts
@@ -9,7 +9,6 @@ export default async function(): Promise<Meta> {
 	} else {
 		return Metas.save({
 			id: genId(),
-			hiddenTags: []
 		} as Meta);
 	}
 }
diff --git a/src/misc/fetch-proxy-account.ts b/src/misc/fetch-proxy-account.ts
index d60fa9b313..17b021e91e 100644
--- a/src/misc/fetch-proxy-account.ts
+++ b/src/misc/fetch-proxy-account.ts
@@ -1,8 +1,9 @@
 import fetchMeta from './fetch-meta';
 import { ILocalUser } from '../models/entities/user';
 import { Users } from '../models';
+import { ensure } from '../prelude/ensure';
 
 export async function fetchProxyAccount(): Promise<ILocalUser> {
 	const meta = await fetchMeta();
-	return await Users.findOne({ username: meta.proxyAccount, host: null }) as ILocalUser;
+	return await Users.findOne({ username: meta.proxyAccount!, host: null }).then(ensure) as ILocalUser;
 }
diff --git a/src/misc/identifiable-error.ts b/src/misc/identifiable-error.ts
index 1edd26cd18..2d7c6bd0c6 100644
--- a/src/misc/identifiable-error.ts
+++ b/src/misc/identifiable-error.ts
@@ -7,7 +7,7 @@ export class IdentifiableError extends Error {
 
 	constructor(id: string, message?: string) {
 		super(message);
-		this.message = message;
+		this.message = message || '';
 		this.id = id;
 	}
 }
diff --git a/src/misc/nyaize.ts b/src/misc/nyaize.ts
index 8b06300eab..918e7d63fd 100644
--- a/src/misc/nyaize.ts
+++ b/src/misc/nyaize.ts
@@ -3,7 +3,7 @@ export function nyaize(text: string): string {
 		// ja-JP
 		.replace(/な/g, 'にゃ').replace(/ナ/g, 'ニャ').replace(/ナ/g, 'ニャ')
 		// ko-KR
-		.replace(/[나-낳]/g, (match: string) => String.fromCharCode(
-			match.codePointAt(0)  + '냐'.charCodeAt(0) - '나'.charCodeAt(0)
+		.replace(/[나-낳]/g, match => String.fromCharCode(
+			match.codePointAt(0)! + '냐'.charCodeAt(0) - '나'.charCodeAt(0)
 		));
 }
diff --git a/src/misc/schema.ts b/src/misc/schema.ts
index e5c24dd468..7c17953d97 100644
--- a/src/misc/schema.ts
+++ b/src/misc/schema.ts
@@ -19,8 +19,8 @@ type MyType<T extends Schema> = {
 export type SchemaType<p extends Schema> =
 	p['type'] extends 'number' ? number :
 	p['type'] extends 'string' ? string :
-	p['type'] extends 'array' ? MyType<p['items']>[] :
-	p['type'] extends 'object' ? ObjType<p['properties']> :
+	p['type'] extends 'array' ? MyType<NonNullable<p['items']>>[] :
+	p['type'] extends 'object' ? ObjType<NonNullable<p['properties']>> :
 	any;
 
 export function convertOpenApiSchema(schema: Schema) {
diff --git a/src/models/entities/poll.ts b/src/models/entities/poll.ts
index c0ad5547bd..6bb67163a2 100644
--- a/src/models/entities/poll.ts
+++ b/src/models/entities/poll.ts
@@ -67,5 +67,5 @@ export type IPoll = {
 	choices: string[];
 	votes?: number[];
 	multiple: boolean;
-	expiresAt: Date;
+	expiresAt: Date | null;
 };
diff --git a/src/models/repositories/abuse-user-report.ts b/src/models/repositories/abuse-user-report.ts
index c72a582c04..f619d6e37f 100644
--- a/src/models/repositories/abuse-user-report.ts
+++ b/src/models/repositories/abuse-user-report.ts
@@ -2,6 +2,7 @@ import { EntityRepository, Repository } from 'typeorm';
 import { Users } from '..';
 import rap from '@prezzemolo/rap';
 import { AbuseUserReport } from '../entities/abuse-user-report';
+import { ensure } from '../../prelude/ensure';
 
 @EntityRepository(AbuseUserReport)
 export class AbuseUserReportRepository extends Repository<AbuseUserReport> {
@@ -14,7 +15,7 @@ export class AbuseUserReportRepository extends Repository<AbuseUserReport> {
 	public async pack(
 		src: AbuseUserReport['id'] | AbuseUserReport,
 	) {
-		const report = typeof src === 'object' ? src : await this.findOne(src);
+		const report = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
 		return await rap({
 			id: report.id,
diff --git a/src/models/repositories/app.ts b/src/models/repositories/app.ts
index 2e3323baf8..a0c0cf68cb 100644
--- a/src/models/repositories/app.ts
+++ b/src/models/repositories/app.ts
@@ -1,6 +1,7 @@
 import { EntityRepository, Repository } from 'typeorm';
 import { App } from '../entities/app';
 import { AccessTokens } from '..';
+import { ensure } from '../../prelude/ensure';
 
 @EntityRepository(App)
 export class AppRepository extends Repository<App> {
@@ -19,7 +20,7 @@ export class AppRepository extends Repository<App> {
 			includeProfileImageIds: false
 		}, options);
 
-		const app = typeof src === 'object' ? src : await this.findOne(src);
+		const app = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
 		return {
 			id: app.id,
diff --git a/src/models/repositories/auth-session.ts b/src/models/repositories/auth-session.ts
index 76e3ddf9ab..540c5466f5 100644
--- a/src/models/repositories/auth-session.ts
+++ b/src/models/repositories/auth-session.ts
@@ -2,6 +2,7 @@ import { EntityRepository, Repository } from 'typeorm';
 import { Apps } from '..';
 import rap from '@prezzemolo/rap';
 import { AuthSession } from '../entities/auth-session';
+import { ensure } from '../../prelude/ensure';
 
 @EntityRepository(AuthSession)
 export class AuthSessionRepository extends Repository<AuthSession> {
@@ -9,7 +10,7 @@ export class AuthSessionRepository extends Repository<AuthSession> {
 		src: AuthSession['id'] | AuthSession,
 		me?: any
 	) {
-		const session = typeof src === 'object' ? src : await this.findOne(src);
+		const session = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
 		return await rap({
 			id: session.id,
diff --git a/src/models/repositories/blocking.ts b/src/models/repositories/blocking.ts
index 81f3866131..e18aa591f3 100644
--- a/src/models/repositories/blocking.ts
+++ b/src/models/repositories/blocking.ts
@@ -2,6 +2,7 @@ import { EntityRepository, Repository } from 'typeorm';
 import { Users } from '..';
 import rap from '@prezzemolo/rap';
 import { Blocking } from '../entities/blocking';
+import { ensure } from '../../prelude/ensure';
 
 @EntityRepository(Blocking)
 export class BlockingRepository extends Repository<Blocking> {
@@ -16,7 +17,7 @@ export class BlockingRepository extends Repository<Blocking> {
 		src: Blocking['id'] | Blocking,
 		me?: any
 	) {
-		const blocking = typeof src === 'object' ? src : await this.findOne(src);
+		const blocking = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
 		return await rap({
 			id: blocking.id,
diff --git a/src/models/repositories/drive-file.ts b/src/models/repositories/drive-file.ts
index 817677fa3b..003e350713 100644
--- a/src/models/repositories/drive-file.ts
+++ b/src/models/repositories/drive-file.ts
@@ -4,6 +4,7 @@ import { Users, DriveFolders } from '..';
 import rap from '@prezzemolo/rap';
 import { User } from '../entities/user';
 import { toPuny } from '../../misc/convert-host';
+import { ensure } from '../../prelude/ensure';
 
 @EntityRepository(DriveFile)
 export class DriveFileRepository extends Repository<DriveFile> {
@@ -91,7 +92,7 @@ export class DriveFileRepository extends Repository<DriveFile> {
 			self: false
 		}, options);
 
-		const file = typeof src === 'object' ? src : await this.findOne(src);
+		const file = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
 		return await rap({
 			id: file.id,
@@ -108,7 +109,7 @@ export class DriveFileRepository extends Repository<DriveFile> {
 			folder: opts.detail && file.folderId ? DriveFolders.pack(file.folderId, {
 				detail: true
 			}) : null,
-			user: opts.withUser ? Users.pack(file.userId) : null
+			user: opts.withUser ? Users.pack(file.userId!) : null
 		});
 	}
 }
diff --git a/src/models/repositories/drive-folder.ts b/src/models/repositories/drive-folder.ts
index faf0f353aa..ce88adefa4 100644
--- a/src/models/repositories/drive-folder.ts
+++ b/src/models/repositories/drive-folder.ts
@@ -2,6 +2,7 @@ import { EntityRepository, Repository } from 'typeorm';
 import { DriveFolders, DriveFiles } from '..';
 import rap from '@prezzemolo/rap';
 import { DriveFolder } from '../entities/drive-folder';
+import { ensure } from '../../prelude/ensure';
 
 @EntityRepository(DriveFolder)
 export class DriveFolderRepository extends Repository<DriveFolder> {
@@ -22,7 +23,7 @@ export class DriveFolderRepository extends Repository<DriveFolder> {
 			detail: false
 		}, options);
 
-		const folder = typeof src === 'object' ? src : await this.findOne(src);
+		const folder = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
 		return await rap({
 			id: folder.id,
diff --git a/src/models/repositories/follow-request.ts b/src/models/repositories/follow-request.ts
index bead093b21..451ed8e2d5 100644
--- a/src/models/repositories/follow-request.ts
+++ b/src/models/repositories/follow-request.ts
@@ -1,6 +1,7 @@
 import { EntityRepository, Repository } from 'typeorm';
 import { FollowRequest } from '../entities/follow-request';
 import { Users } from '..';
+import { ensure } from '../../prelude/ensure';
 
 @EntityRepository(FollowRequest)
 export class FollowRequestRepository extends Repository<FollowRequest> {
@@ -8,7 +9,7 @@ export class FollowRequestRepository extends Repository<FollowRequest> {
 		src: FollowRequest['id'] | FollowRequest,
 		me?: any
 	) {
-		const request = typeof src === 'object' ? src : await this.findOne(src);
+		const request = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
 		return {
 			id: request.id,
diff --git a/src/models/repositories/following.ts b/src/models/repositories/following.ts
index 02253d272d..3fff57866f 100644
--- a/src/models/repositories/following.ts
+++ b/src/models/repositories/following.ts
@@ -2,9 +2,50 @@ import { EntityRepository, Repository } from 'typeorm';
 import { Users } from '..';
 import rap from '@prezzemolo/rap';
 import { Following } from '../entities/following';
+import { ensure } from '../../prelude/ensure';
+
+type LocalFollowerFollowing = Following & {
+	followerHost: null;
+	followerInbox: null;
+	followerSharedInbox: null;
+};
+
+type RemoteFollowerFollowing = Following & {
+	followerHost: string;
+	followerInbox: string;
+	followerSharedInbox: string;
+};
+
+type LocalFolloweeFollowing = Following & {
+	followeeHost: null;
+	followeeInbox: null;
+	followeeSharedInbox: null;
+};
+
+type RemoteFolloweeFollowing = Following & {
+	followeeHost: string;
+	followeeInbox: string;
+	followeeSharedInbox: string;
+};
 
 @EntityRepository(Following)
 export class FollowingRepository extends Repository<Following> {
+	public isLocalFollower(following: Following): following is LocalFollowerFollowing {
+		return following.followerHost == null;
+	}
+
+	public isRemoteFollower(following: Following): following is RemoteFollowerFollowing {
+		return following.followerHost != null;
+	}
+
+	public isLocalFollowee(following: Following): following is LocalFolloweeFollowing {
+		return following.followeeHost == null;
+	}
+
+	public isRemoteFollowee(following: Following): following is RemoteFolloweeFollowing {
+		return following.followeeHost != null;
+	}
+
 	public packMany(
 		followings: any[],
 		me?: any,
@@ -24,7 +65,7 @@ export class FollowingRepository extends Repository<Following> {
 			populateFollower?: boolean;
 		}
 	) {
-		const following = typeof src === 'object' ? src : await this.findOne(src);
+		const following = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
 		if (opts == null) opts = {};
 
diff --git a/src/models/repositories/games/reversi/game.ts b/src/models/repositories/games/reversi/game.ts
index f0cb6ff905..c380f5251e 100644
--- a/src/models/repositories/games/reversi/game.ts
+++ b/src/models/repositories/games/reversi/game.ts
@@ -1,6 +1,7 @@
 import { EntityRepository, Repository } from 'typeorm';
 import { Users } from '../../..';
 import { ReversiGame } from '../../../entities/games/reversi/game';
+import { ensure } from '../../../../prelude/ensure';
 
 @EntityRepository(ReversiGame)
 export class ReversiGameRepository extends Repository<ReversiGame> {
@@ -15,7 +16,7 @@ export class ReversiGameRepository extends Repository<ReversiGame> {
 			detail: true
 		}, options);
 
-		const game = typeof src === 'object' ? src : await this.findOne(src);
+		const game = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 		const meId = me ? typeof me === 'string' ? me : me.id : null;
 
 		return {
diff --git a/src/models/repositories/games/reversi/matching.ts b/src/models/repositories/games/reversi/matching.ts
index 3612ac5c47..4d99c6ef76 100644
--- a/src/models/repositories/games/reversi/matching.ts
+++ b/src/models/repositories/games/reversi/matching.ts
@@ -2,6 +2,7 @@ import { EntityRepository, Repository } from 'typeorm';
 import rap from '@prezzemolo/rap';
 import { ReversiMatching } from '../../../entities/games/reversi/matching';
 import { Users } from '../../..';
+import { ensure } from '../../../../prelude/ensure';
 
 @EntityRepository(ReversiMatching)
 export class ReversiMatchingRepository extends Repository<ReversiMatching> {
@@ -9,7 +10,7 @@ export class ReversiMatchingRepository extends Repository<ReversiMatching> {
 		src: ReversiMatching['id'] | ReversiMatching,
 		me: any
 	) {
-		const matching = typeof src === 'object' ? src : await this.findOne(src);
+		const matching = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
 		return await rap({
 			id: matching.id,
diff --git a/src/models/repositories/messaging-message.ts b/src/models/repositories/messaging-message.ts
index b87b30388a..6659273539 100644
--- a/src/models/repositories/messaging-message.ts
+++ b/src/models/repositories/messaging-message.ts
@@ -1,6 +1,7 @@
 import { EntityRepository, Repository } from 'typeorm';
 import { MessagingMessage } from '../entities/messaging-message';
 import { Users, DriveFiles } from '..';
+import { ensure } from '../../prelude/ensure';
 
 @EntityRepository(MessagingMessage)
 export class MessagingMessageRepository extends Repository<MessagingMessage> {
@@ -19,7 +20,7 @@ export class MessagingMessageRepository extends Repository<MessagingMessage> {
 			populateRecipient: true
 		};
 
-		const message = typeof src === 'object' ? src : await this.findOne(src);
+		const message = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
 		return {
 			id: message.id,
diff --git a/src/models/repositories/muting.ts b/src/models/repositories/muting.ts
index cd98cb4fec..1812e2e713 100644
--- a/src/models/repositories/muting.ts
+++ b/src/models/repositories/muting.ts
@@ -2,6 +2,7 @@ import { EntityRepository, Repository } from 'typeorm';
 import { Users } from '..';
 import rap from '@prezzemolo/rap';
 import { Muting } from '../entities/muting';
+import { ensure } from '../../prelude/ensure';
 
 @EntityRepository(Muting)
 export class MutingRepository extends Repository<Muting> {
@@ -16,7 +17,7 @@ export class MutingRepository extends Repository<Muting> {
 		src: Muting['id'] | Muting,
 		me?: any
 	) {
-		const muting = typeof src === 'object' ? src : await this.findOne(src);
+		const muting = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
 		return await rap({
 			id: muting.id,
diff --git a/src/models/repositories/note-favorite.ts b/src/models/repositories/note-favorite.ts
index 4526461e69..f428903c13 100644
--- a/src/models/repositories/note-favorite.ts
+++ b/src/models/repositories/note-favorite.ts
@@ -1,6 +1,7 @@
 import { EntityRepository, Repository } from 'typeorm';
 import { NoteFavorite } from '../entities/note-favorite';
 import { Notes } from '..';
+import { ensure } from '../../prelude/ensure';
 
 @EntityRepository(NoteFavorite)
 export class NoteFavoriteRepository extends Repository<NoteFavorite> {
@@ -15,7 +16,7 @@ export class NoteFavoriteRepository extends Repository<NoteFavorite> {
 		src: NoteFavorite['id'] | NoteFavorite,
 		me?: any
 	) {
-		const favorite = typeof src === 'object' ? src : await this.findOne(src);
+		const favorite = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
 		return {
 			id: favorite.id,
diff --git a/src/models/repositories/note-reaction.ts b/src/models/repositories/note-reaction.ts
index 7189da8e20..28191d4ab0 100644
--- a/src/models/repositories/note-reaction.ts
+++ b/src/models/repositories/note-reaction.ts
@@ -1,6 +1,7 @@
 import { EntityRepository, Repository } from 'typeorm';
 import { NoteReaction } from '../entities/note-reaction';
 import { Users } from '..';
+import { ensure } from '../../prelude/ensure';
 
 @EntityRepository(NoteReaction)
 export class NoteReactionRepository extends Repository<NoteReaction> {
@@ -8,7 +9,7 @@ export class NoteReactionRepository extends Repository<NoteReaction> {
 		src: NoteReaction['id'] | NoteReaction,
 		me?: any
 	) {
-		const reaction = typeof src === 'object' ? src : await this.findOne(src);
+		const reaction = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
 		return {
 			id: reaction.id,
diff --git a/src/models/repositories/note.ts b/src/models/repositories/note.ts
index 01bf8cf87c..77cf00849f 100644
--- a/src/models/repositories/note.ts
+++ b/src/models/repositories/note.ts
@@ -5,6 +5,7 @@ import { unique, concat } from '../../prelude/array';
 import { nyaize } from '../../misc/nyaize';
 import { Emojis, Users, Apps, PollVotes, DriveFiles, NoteReactions, Followings, Polls } from '..';
 import rap from '@prezzemolo/rap';
+import { ensure } from '../../prelude/ensure';
 
 @EntityRepository(Note)
 export class NoteRepository extends Repository<Note> {
@@ -12,7 +13,7 @@ export class NoteRepository extends Repository<Note> {
 		return x.trim().length <= 100;
 	}
 
-	private async hideNote(packedNote: any, meId: User['id']) {
+	private async hideNote(packedNote: any, meId: User['id'] | null) {
 		let hide = false;
 
 		// visibility が specified かつ自分が指定されていなかったら非表示
@@ -75,7 +76,7 @@ export class NoteRepository extends Repository<Note> {
 
 	public packMany(
 		notes: (Note['id'] | Note)[],
-		me?: User['id'] | User,
+		me?: User['id'] | User | null | undefined,
 		options?: {
 			detail?: boolean;
 			skipHide?: boolean;
@@ -86,7 +87,7 @@ export class NoteRepository extends Repository<Note> {
 
 	public async pack(
 		src: Note['id'] | Note,
-		me?: User['id'] | User,
+		me?: User['id'] | User | null | undefined,
 		options?: {
 			detail?: boolean;
 			skipHide?: boolean;
@@ -98,11 +99,11 @@ export class NoteRepository extends Repository<Note> {
 		}, options);
 
 		const meId = me ? typeof me === 'string' ? me : me.id : null;
-		const note = typeof src === 'object' ? src : await this.findOne(src);
+		const note = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 		const host = note.userHost;
 
 		async function populatePoll() {
-			const poll = await Polls.findOne({ noteId: note.id });
+			const poll = await Polls.findOne({ noteId: note.id }).then(ensure);
 			const choices = poll.choices.map(c => ({
 				text: c,
 				votes: poll.votes[poll.choices.indexOf(c)],
@@ -111,7 +112,7 @@ export class NoteRepository extends Repository<Note> {
 
 			if (poll.multiple) {
 				const votes = await PollVotes.find({
-					userId: meId,
+					userId: meId!,
 					noteId: note.id
 				});
 
@@ -121,7 +122,7 @@ export class NoteRepository extends Repository<Note> {
 				}
 			} else {
 				const vote = await PollVotes.findOne({
-					userId: meId,
+					userId: meId!,
 					noteId: note.id
 				});
 
@@ -139,7 +140,7 @@ export class NoteRepository extends Repository<Note> {
 
 		async function populateMyReaction() {
 			const reaction = await NoteReactions.findOne({
-				userId: meId,
+				userId: meId!,
 				noteId: note.id,
 			});
 
diff --git a/src/models/repositories/notification.ts b/src/models/repositories/notification.ts
index 9bc569cd3f..4781d4c065 100644
--- a/src/models/repositories/notification.ts
+++ b/src/models/repositories/notification.ts
@@ -2,6 +2,7 @@ import { EntityRepository, Repository } from 'typeorm';
 import { Users, Notes } from '..';
 import rap from '@prezzemolo/rap';
 import { Notification } from '../entities/notification';
+import { ensure } from '../../prelude/ensure';
 
 @EntityRepository(Notification)
 export class NotificationRepository extends Repository<Notification> {
@@ -14,7 +15,7 @@ export class NotificationRepository extends Repository<Notification> {
 	public async pack(
 		src: Notification['id'] | Notification,
 	) {
-		const notification = typeof src === 'object' ? src : await this.findOne(src);
+		const notification = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
 		return await rap({
 			id: notification.id,
@@ -23,23 +24,23 @@ export class NotificationRepository extends Repository<Notification> {
 			userId: notification.notifierId,
 			user: Users.pack(notification.notifier || notification.notifierId),
 			...(notification.type === 'mention' ? {
-				note: Notes.pack(notification.note || notification.noteId),
+				note: Notes.pack(notification.note || notification.noteId!),
 			} : {}),
 			...(notification.type === 'reply' ? {
-				note: Notes.pack(notification.note || notification.noteId),
+				note: Notes.pack(notification.note || notification.noteId!),
 			} : {}),
 			...(notification.type === 'renote' ? {
-				note: Notes.pack(notification.note || notification.noteId),
+				note: Notes.pack(notification.note || notification.noteId!),
 			} : {}),
 			...(notification.type === 'quote' ? {
-				note: Notes.pack(notification.note || notification.noteId),
+				note: Notes.pack(notification.note || notification.noteId!),
 			} : {}),
 			...(notification.type === 'reaction' ? {
-				note: Notes.pack(notification.note || notification.noteId),
+				note: Notes.pack(notification.note || notification.noteId!),
 				reaction: notification.reaction
 			} : {}),
 			...(notification.type === 'pollVote' ? {
-				note: Notes.pack(notification.note || notification.noteId),
+				note: Notes.pack(notification.note || notification.noteId!),
 				choice: notification.choice
 			} : {})
 		});
diff --git a/src/models/repositories/user-list.ts b/src/models/repositories/user-list.ts
index 921c18ca7a..fbf81b8886 100644
--- a/src/models/repositories/user-list.ts
+++ b/src/models/repositories/user-list.ts
@@ -1,12 +1,13 @@
 import { EntityRepository, Repository } from 'typeorm';
 import { UserList } from '../entities/user-list';
+import { ensure } from '../../prelude/ensure';
 
 @EntityRepository(UserList)
 export class UserListRepository extends Repository<UserList> {
 	public async pack(
-		src: any,
+		src: UserList['id'] | UserList,
 	) {
-		const userList = typeof src === 'object' ? src : await this.findOne(src);
+		const userList = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 
 		return {
 			id: userList.id,
diff --git a/src/models/repositories/user.ts b/src/models/repositories/user.ts
index d7f2c3d040..cddb77ffae 100644
--- a/src/models/repositories/user.ts
+++ b/src/models/repositories/user.ts
@@ -2,6 +2,7 @@ import { EntityRepository, Repository, In } from 'typeorm';
 import { User, ILocalUser, IRemoteUser } from '../entities/user';
 import { Emojis, Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles } from '..';
 import rap from '@prezzemolo/rap';
+import { ensure } from '../../prelude/ensure';
 
 @EntityRepository(User)
 export class UserRepository extends Repository<User> {
@@ -51,7 +52,7 @@ export class UserRepository extends Repository<User> {
 
 	public packMany(
 		users: (User['id'] | User)[],
-		me?: User['id'] | User,
+		me?: User['id'] | User | null | undefined,
 		options?: {
 			detail?: boolean,
 			includeSecrets?: boolean,
@@ -63,7 +64,7 @@ export class UserRepository extends Repository<User> {
 
 	public async pack(
 		src: User['id'] | User,
-		me?: User['id'] | User,
+		me?: User['id'] | User | null | undefined,
 		options?: {
 			detail?: boolean,
 			includeSecrets?: boolean,
@@ -75,12 +76,12 @@ export class UserRepository extends Repository<User> {
 			includeSecrets: false
 		}, options);
 
-		const user = typeof src === 'object' ? src : await this.findOne(src);
+		const user = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
 		const meId = me ? typeof me === 'string' ? me : me.id : null;
 
 		const relation = meId && (meId !== user.id) && opts.detail ? await this.getRelation(meId, user.id) : null;
 		const pins = opts.detail ? await UserNotePinings.find({ userId: user.id }) : [];
-		const profile = opts.detail ? await UserProfiles.findOne({ userId: user.id }) : null;
+		const profile = opts.detail ? await UserProfiles.findOne({ userId: user.id }).then(ensure) : null;
 
 		return await rap({
 			id: user.id,
@@ -117,12 +118,12 @@ export class UserRepository extends Repository<User> {
 			} : {}),
 
 			...(opts.detail ? {
-				url: profile.url,
+				url: profile!.url,
 				createdAt: user.createdAt,
 				updatedAt: user.updatedAt,
-				description: profile.description,
-				location: profile.location,
-				birthday: profile.birthday,
+				description: profile!.description,
+				location: profile!.location,
+				birthday: profile!.birthday,
 				followersCount: user.followersCount,
 				followingCount: user.followingCount,
 				notesCount: user.notesCount,
@@ -135,9 +136,9 @@ export class UserRepository extends Repository<User> {
 			...(opts.detail && meId === user.id ? {
 				avatarId: user.avatarId,
 				bannerId: user.bannerId,
-				autoWatch: profile.autoWatch,
-				alwaysMarkNsfw: profile.alwaysMarkNsfw,
-				carefulBot: profile.carefulBot,
+				autoWatch: profile!.autoWatch,
+				alwaysMarkNsfw: profile!.alwaysMarkNsfw,
+				carefulBot: profile!.carefulBot,
 				hasUnreadMessagingMessage: MessagingMessages.count({
 					where: {
 						recipientId: user.id,
@@ -158,9 +159,9 @@ export class UserRepository extends Repository<User> {
 			} : {}),
 
 			...(opts.includeSecrets ? {
-				clientData: profile.clientData,
-				email: profile.email,
-				emailVerified: profile.emailVerified,
+				clientData: profile!.clientData,
+				email: profile!.email,
+				emailVerified: profile!.emailVerified,
 			} : {}),
 
 			...(relation ? {
diff --git a/src/prelude/ensure.ts b/src/prelude/ensure.ts
new file mode 100644
index 0000000000..90bf05538a
--- /dev/null
+++ b/src/prelude/ensure.ts
@@ -0,0 +1,7 @@
+export function ensure<T>(x: T): NonNullable<T> {
+	if (x == null) {
+		throw 'ぬるぽ';
+	} else {
+		return x!;
+	}
+}
diff --git a/src/queue/index.ts b/src/queue/index.ts
index 728c43c6ac..1ab59fd18f 100644
--- a/src/queue/index.ts
+++ b/src/queue/index.ts
@@ -12,7 +12,7 @@ import { queueLogger } from './logger';
 import { DriveFile } from '../models/entities/drive-file';
 
 function initializeQueue(name: string) {
-	return new Queue(name, config.redis != null ? {
+	return new Queue(name, {
 		redis: {
 			port: config.redis.port,
 			host: config.redis.host,
@@ -20,7 +20,7 @@ function initializeQueue(name: string) {
 			db: config.redis.db || 0,
 		},
 		prefix: config.redis.prefix ? `${config.redis.prefix}:queue` : 'queue'
-	} : null);
+	});
 }
 
 export const deliverQueue = initializeQueue('deliver');
diff --git a/src/queue/processors/db/delete-drive-files.ts b/src/queue/processors/db/delete-drive-files.ts
index 5f347fb588..491734acc6 100644
--- a/src/queue/processors/db/delete-drive-files.ts
+++ b/src/queue/processors/db/delete-drive-files.ts
@@ -10,9 +10,11 @@ const logger = queueLogger.createSubLogger('delete-drive-files');
 export async function deleteDriveFiles(job: Bull.Job, done: any): Promise<void> {
 	logger.info(`Deleting drive files of ${job.data.user.id} ...`);
 
-	const user = await Users.findOne({
-		id: job.data.user.id
-	});
+	const user = await Users.findOne(job.data.user.id);
+	if (user == null) {
+		done();
+		return;
+	}
 
 	let deletedCount = 0;
 	let ended = false;
diff --git a/src/queue/processors/db/export-blocking.ts b/src/queue/processors/db/export-blocking.ts
index c12aa4fca3..44025ec960 100644
--- a/src/queue/processors/db/export-blocking.ts
+++ b/src/queue/processors/db/export-blocking.ts
@@ -14,9 +14,11 @@ const logger = queueLogger.createSubLogger('export-blocking');
 export async function exportBlocking(job: Bull.Job, done: any): Promise<void> {
 	logger.info(`Exporting blocking of ${job.data.user.id} ...`);
 
-	const user = await Users.findOne({
-		id: job.data.user.id
-	});
+	const user = await Users.findOne(job.data.user.id);
+	if (user == null) {
+		done();
+		return;
+	}
 
 	// Create temp file
 	const [path, cleanup] = await new Promise<[string, any]>((res, rej) => {
@@ -56,6 +58,10 @@ export async function exportBlocking(job: Bull.Job, done: any): Promise<void> {
 
 		for (const block of blockings) {
 			const u = await Users.findOne({ id: block.blockeeId });
+			if (u == null) {
+				exportedCount++; continue;
+			}
+
 			const content = getFullApAccount(u.username, u.host);
 			await new Promise((res, rej) => {
 				stream.write(content + '\n', err => {
diff --git a/src/queue/processors/db/export-following.ts b/src/queue/processors/db/export-following.ts
index fb30df79fe..81dcf8f93e 100644
--- a/src/queue/processors/db/export-following.ts
+++ b/src/queue/processors/db/export-following.ts
@@ -14,9 +14,11 @@ const logger = queueLogger.createSubLogger('export-following');
 export async function exportFollowing(job: Bull.Job, done: any): Promise<void> {
 	logger.info(`Exporting following of ${job.data.user.id} ...`);
 
-	const user = await Users.findOne({
-		id: job.data.user.id
-	});
+	const user = await Users.findOne(job.data.user.id);
+	if (user == null) {
+		done();
+		return;
+	}
 
 	// Create temp file
 	const [path, cleanup] = await new Promise<[string, any]>((res, rej) => {
@@ -56,6 +58,10 @@ export async function exportFollowing(job: Bull.Job, done: any): Promise<void> {
 
 		for (const following of followings) {
 			const u = await Users.findOne({ id: following.followeeId });
+			if (u == null) {
+				exportedCount++; continue;
+			}
+
 			const content = getFullApAccount(u.username, u.host);
 			await new Promise((res, rej) => {
 				stream.write(content + '\n', err => {
diff --git a/src/queue/processors/db/export-mute.ts b/src/queue/processors/db/export-mute.ts
index 3aed526dc5..f810b6ee8d 100644
--- a/src/queue/processors/db/export-mute.ts
+++ b/src/queue/processors/db/export-mute.ts
@@ -14,9 +14,11 @@ const logger = queueLogger.createSubLogger('export-mute');
 export async function exportMute(job: Bull.Job, done: any): Promise<void> {
 	logger.info(`Exporting mute of ${job.data.user.id} ...`);
 
-	const user = await Users.findOne({
-		id: job.data.user.id
-	});
+	const user = await Users.findOne(job.data.user.id);
+	if (user == null) {
+		done();
+		return;
+	}
 
 	// Create temp file
 	const [path, cleanup] = await new Promise<[string, any]>((res, rej) => {
@@ -56,6 +58,10 @@ export async function exportMute(job: Bull.Job, done: any): Promise<void> {
 
 		for (const mute of mutes) {
 			const u = await Users.findOne({ id: mute.muteeId });
+			if (u == null) {
+				exportedCount++; continue;
+			}
+
 			const content = getFullApAccount(u.username, u.host);
 			await new Promise((res, rej) => {
 				stream.write(content + '\n', err => {
diff --git a/src/queue/processors/db/export-notes.ts b/src/queue/processors/db/export-notes.ts
index 92867ad82e..eaa5caf63f 100644
--- a/src/queue/processors/db/export-notes.ts
+++ b/src/queue/processors/db/export-notes.ts
@@ -9,15 +9,18 @@ import { Users, Notes, Polls } from '../../../models';
 import { MoreThan } from 'typeorm';
 import { Note } from '../../../models/entities/note';
 import { Poll } from '../../../models/entities/poll';
+import { ensure } from '../../../prelude/ensure';
 
 const logger = queueLogger.createSubLogger('export-notes');
 
 export async function exportNotes(job: Bull.Job, done: any): Promise<void> {
 	logger.info(`Exporting notes of ${job.data.user.id} ...`);
 
-	const user = await Users.findOne({
-		id: job.data.user.id
-	});
+	const user = await Users.findOne(job.data.user.id);
+	if (user == null) {
+		done();
+		return;
+	}
 
 	// Create temp file
 	const [path, cleanup] = await new Promise<[string, any]>((res, rej) => {
@@ -67,9 +70,9 @@ export async function exportNotes(job: Bull.Job, done: any): Promise<void> {
 		cursor = notes[notes.length - 1].id;
 
 		for (const note of notes) {
-			let poll: Poll;
+			let poll: Poll | undefined;
 			if (note.hasPoll) {
-				poll = await Polls.findOne({ noteId: note.id });
+				poll = await Polls.findOne({ noteId: note.id }).then(ensure);
 			}
 			const content = JSON.stringify(serialize(note, poll));
 			await new Promise((res, rej) => {
@@ -114,7 +117,7 @@ export async function exportNotes(job: Bull.Job, done: any): Promise<void> {
 	done();
 }
 
-function serialize(note: Note, poll: Poll): any {
+function serialize(note: Note, poll: Poll | null = null): any {
 	return {
 		id: note.id,
 		text: note.text,
diff --git a/src/queue/processors/db/export-user-lists.ts b/src/queue/processors/db/export-user-lists.ts
index f3987cb0d2..5cd978c1aa 100644
--- a/src/queue/processors/db/export-user-lists.ts
+++ b/src/queue/processors/db/export-user-lists.ts
@@ -14,9 +14,11 @@ const logger = queueLogger.createSubLogger('export-user-lists');
 export async function exportUserLists(job: Bull.Job, done: any): Promise<void> {
 	logger.info(`Exporting user lists of ${job.data.user.id} ...`);
 
-	const user = await Users.findOne({
-		id: job.data.user.id
-	});
+	const user = await Users.findOne(job.data.user.id);
+	if (user == null) {
+		done();
+		return;
+	}
 
 	const lists = await UserLists.find({
 		userId: user.id
diff --git a/src/queue/processors/db/import-following.ts b/src/queue/processors/db/import-following.ts
index aae24b22d6..8de3193e46 100644
--- a/src/queue/processors/db/import-following.ts
+++ b/src/queue/processors/db/import-following.ts
@@ -13,13 +13,19 @@ const logger = queueLogger.createSubLogger('import-following');
 export async function importFollowing(job: Bull.Job, done: any): Promise<void> {
 	logger.info(`Importing following of ${job.data.user.id} ...`);
 
-	const user = await Users.findOne({
-		id: job.data.user.id
-	});
+	const user = await Users.findOne(job.data.user.id);
+	if (user == null) {
+		done();
+		return;
+	}
 
 	const file = await DriveFiles.findOne({
 		id: job.data.fileId
 	});
+	if (file == null) {
+		done();
+		return;
+	}
 
 	const csv = await downloadTextFile(file.url);
 
@@ -31,11 +37,11 @@ export async function importFollowing(job: Bull.Job, done: any): Promise<void> {
 		try {
 			const { username, host } = parseAcct(line.trim());
 
-			let target = isSelfHost(host) ? await Users.findOne({
+			let target = isSelfHost(host!) ? await Users.findOne({
 				host: null,
 				usernameLower: username.toLowerCase()
 			}) : await Users.findOne({
-				host: toPuny(host),
+				host: toPuny(host!),
 				usernameLower: username.toLowerCase()
 			});
 
diff --git a/src/queue/processors/db/import-user-lists.ts b/src/queue/processors/db/import-user-lists.ts
index c7273ea6b4..1e852be945 100644
--- a/src/queue/processors/db/import-user-lists.ts
+++ b/src/queue/processors/db/import-user-lists.ts
@@ -14,13 +14,19 @@ const logger = queueLogger.createSubLogger('import-user-lists');
 export async function importUserLists(job: Bull.Job, done: any): Promise<void> {
 	logger.info(`Importing user lists of ${job.data.user.id} ...`);
 
-	const user = await Users.findOne({
-		id: job.data.user.id
-	});
+	const user = await Users.findOne(job.data.user.id);
+	if (user == null) {
+		done();
+		return;
+	}
 
 	const file = await DriveFiles.findOne({
 		id: job.data.fileId
 	});
+	if (file == null) {
+		done();
+		return;
+	}
 
 	const csv = await downloadTextFile(file.url);
 
@@ -43,22 +49,20 @@ export async function importUserLists(job: Bull.Job, done: any): Promise<void> {
 			});
 		}
 
-		let target = isSelfHost(host) ? await Users.findOne({
+		let target = isSelfHost(host!) ? await Users.findOne({
 			host: null,
 			usernameLower: username.toLowerCase()
 		}) : await Users.findOne({
-			host: toPuny(host),
+			host: toPuny(host!),
 			usernameLower: username.toLowerCase()
 		});
 
-		if (host == null && target == null) continue;
-
-		if (await UserListJoinings.findOne({ userListId: list.id, userId: target.id }) != null) continue;
-
 		if (target == null) {
 			target = await resolveUser(username, host);
 		}
 
+		if (await UserListJoinings.findOne({ userListId: list.id, userId: target.id }) != null) continue;
+
 		pushUserToUserList(target, list);
 	}
 
diff --git a/src/queue/processors/deliver.ts b/src/queue/processors/deliver.ts
index b9701c0c65..8837c80d87 100644
--- a/src/queue/processors/deliver.ts
+++ b/src/queue/processors/deliver.ts
@@ -7,7 +7,7 @@ import { instanceChart } from '../../services/chart';
 
 const logger = new Logger('deliver');
 
-let latest: string = null;
+let latest: string | null = null;
 
 export default async (job: Bull.Job) => {
 	const { host } = new URL(job.data.to);
diff --git a/src/queue/processors/inbox.ts b/src/queue/processors/inbox.ts
index 35b0ce5386..4deaef2ae3 100644
--- a/src/queue/processors/inbox.ts
+++ b/src/queue/processors/inbox.ts
@@ -14,6 +14,7 @@ import { UserPublickey } from '../../models/entities/user-publickey';
 import fetchMeta from '../../misc/fetch-meta';
 import { toPuny } from '../../misc/convert-host';
 import { validActor } from '../../remote/activitypub/type';
+import { ensure } from '../../prelude/ensure';
 
 const logger = new Logger('inbox');
 
@@ -35,7 +36,7 @@ export default async (job: Bull.Job): Promise<void> => {
 
 	if (keyIdLower.startsWith('acct:')) {
 		const acct = parseAcct(keyIdLower.slice('acct:'.length));
-		const host = toPuny(acct.host);
+		const host = acct.host ? toPuny(acct.host) : null;
 		const username = toPuny(acct.username);
 
 		if (host === null) {
@@ -64,9 +65,7 @@ export default async (job: Bull.Job): Promise<void> => {
 			host: host
 		}) as IRemoteUser;
 
-		key = await UserPublickeys.findOne({
-			userId: user.id
-		});
+		key = await UserPublickeys.findOne(user.id).then(ensure);
 	} else {
 		// アクティビティ内のホストの検証
 		const host = toPuny(new URL(signature.keyId).hostname);
@@ -87,7 +86,7 @@ export default async (job: Bull.Job): Promise<void> => {
 
 		key = await UserPublickeys.findOne({
 			keyId: signature.keyId
-		});
+		}).then(ensure);
 
 		user = await Users.findOne(key.userId) as IRemoteUser;
 	}
diff --git a/src/remote/activitypub/kernel/accept/follow.ts b/src/remote/activitypub/kernel/accept/follow.ts
index 816fcbadbf..f3e517ad9f 100644
--- a/src/remote/activitypub/kernel/accept/follow.ts
+++ b/src/remote/activitypub/kernel/accept/follow.ts
@@ -6,9 +6,10 @@ import { Users } from '../../../../models';
 
 export default async (actor: IRemoteUser, activity: IFollow): Promise<void> => {
 	const id = typeof activity.actor == 'string' ? activity.actor : activity.actor.id;
+	if (id == null) throw 'missing id';
 
 	if (!id.startsWith(config.url + '/')) {
-		return null;
+		return;
 	}
 
 	const follower = await Users.findOne({
diff --git a/src/remote/activitypub/kernel/add/index.ts b/src/remote/activitypub/kernel/add/index.ts
index d16f0a4a0d..a5b2687416 100644
--- a/src/remote/activitypub/kernel/add/index.ts
+++ b/src/remote/activitypub/kernel/add/index.ts
@@ -14,6 +14,7 @@ export default async (actor: IRemoteUser, activity: IAdd): Promise<void> => {
 
 	if (activity.target === actor.featured) {
 		const note = await resolveNote(activity.object);
+		if (note == null) throw new Error('note not found');
 		await addPinned(actor, note.id);
 		return;
 	}
diff --git a/src/remote/activitypub/kernel/announce/note.ts b/src/remote/activitypub/kernel/announce/note.ts
index 403fc66bed..f9822c5187 100644
--- a/src/remote/activitypub/kernel/announce/note.ts
+++ b/src/remote/activitypub/kernel/announce/note.ts
@@ -53,16 +53,16 @@ export default async function(resolver: Resolver, actor: IRemoteUser, activity:
 	logger.info(`Creating the (Re)Note: ${uri}`);
 
 	//#region Visibility
-	const visibility = getVisibility(activity.to, activity.cc, actor);
+	const visibility = getVisibility(activity.to || [], activity.cc || [], actor);
 
 	let visibleUsers: User[] = [];
 	if (visibility == 'specified') {
-		visibleUsers = await Promise.all(note.to.map(uri => resolvePerson(uri)));
+		visibleUsers = await Promise.all((note.to || []).map(uri => resolvePerson(uri)));
 	}
 	//#endergion
 
 	await post(actor, {
-		createdAt: new Date(activity.published),
+		createdAt: activity.published ? new Date(activity.published) : null,
 		renote,
 		visibility,
 		visibleUsers,
@@ -75,9 +75,6 @@ type visibility = 'public' | 'home' | 'followers' | 'specified';
 function getVisibility(to: string[], cc: string[], actor: IRemoteUser): visibility {
 	const PUBLIC = 'https://www.w3.org/ns/activitystreams#Public';
 
-	to = to || [];
-	cc = cc || [];
-
 	if (to.includes(PUBLIC)) {
 		return 'public';
 	} else if (cc.includes(PUBLIC)) {
diff --git a/src/remote/activitypub/kernel/block/index.ts b/src/remote/activitypub/kernel/block/index.ts
index 48e251dd9b..19e33eb7dd 100644
--- a/src/remote/activitypub/kernel/block/index.ts
+++ b/src/remote/activitypub/kernel/block/index.ts
@@ -9,13 +9,14 @@ const logger = apLogger;
 
 export default async (actor: IRemoteUser, activity: IBlock): Promise<void> => {
 	const id = typeof activity.object == 'string' ? activity.object : activity.object.id;
+	if (id == null) throw 'missing id';
 
 	const uri = activity.id || activity;
 
 	logger.info(`Block: ${uri}`);
 
 	if (!id.startsWith(config.url + '/')) {
-		return null;
+		return;
 	}
 
 	const blockee = await Users.findOne(id.split('/').pop());
diff --git a/src/remote/activitypub/kernel/follow.ts b/src/remote/activitypub/kernel/follow.ts
index e6c8833f3a..d37404502f 100644
--- a/src/remote/activitypub/kernel/follow.ts
+++ b/src/remote/activitypub/kernel/follow.ts
@@ -6,9 +6,10 @@ import { Users } from '../../../models';
 
 export default async (actor: IRemoteUser, activity: IFollow): Promise<void> => {
 	const id = typeof activity.object == 'string' ? activity.object : activity.object.id;
+	if (id == null) throw 'missing id';
 
 	if (!id.startsWith(config.url + '/')) {
-		return null;
+		return;
 	}
 
 	const followee = await Users.findOne(id.split('/').pop());
diff --git a/src/remote/activitypub/kernel/index.ts b/src/remote/activitypub/kernel/index.ts
index 4a57d0675e..d1251817fa 100644
--- a/src/remote/activitypub/kernel/index.ts
+++ b/src/remote/activitypub/kernel/index.ts
@@ -71,7 +71,7 @@ const self = async (actor: IRemoteUser, activity: Object): Promise<void> => {
 
 	default:
 		apLogger.warn(`unknown activity type: ${(activity as any).type}`);
-		return null;
+		return;
 	}
 };
 
diff --git a/src/remote/activitypub/kernel/like.ts b/src/remote/activitypub/kernel/like.ts
index 86dd8fb33d..d4fa7bf387 100644
--- a/src/remote/activitypub/kernel/like.ts
+++ b/src/remote/activitypub/kernel/like.ts
@@ -5,6 +5,7 @@ import { Notes } from '../../../models';
 
 export default async (actor: IRemoteUser, activity: ILike) => {
 	const id = typeof activity.object == 'string' ? activity.object : activity.object.id;
+	if (id == null) throw 'missing id';
 
 	// Transform:
 	// https://misskey.ex/notes/xxxx to
diff --git a/src/remote/activitypub/kernel/reject/follow.ts b/src/remote/activitypub/kernel/reject/follow.ts
index b06ae6fb96..91689339ab 100644
--- a/src/remote/activitypub/kernel/reject/follow.ts
+++ b/src/remote/activitypub/kernel/reject/follow.ts
@@ -6,9 +6,10 @@ import { Users } from '../../../../models';
 
 export default async (actor: IRemoteUser, activity: IFollow): Promise<void> => {
 	const id = typeof activity.actor == 'string' ? activity.actor : activity.actor.id;
+	if (id == null) throw 'missing id';
 
 	if (!id.startsWith(config.url + '/')) {
-		return null;
+		return;
 	}
 
 	const follower = await Users.findOne(id.split('/').pop());
diff --git a/src/remote/activitypub/kernel/remove/index.ts b/src/remote/activitypub/kernel/remove/index.ts
index ae33be59dc..32b8d66471 100644
--- a/src/remote/activitypub/kernel/remove/index.ts
+++ b/src/remote/activitypub/kernel/remove/index.ts
@@ -14,6 +14,7 @@ export default async (actor: IRemoteUser, activity: IRemove): Promise<void> => {
 
 	if (activity.target === actor.featured) {
 		const note = await resolveNote(activity.object);
+		if (note == null) throw new Error('note not found');
 		await removePinned(actor, note.id);
 		return;
 	}
diff --git a/src/remote/activitypub/kernel/undo/block.ts b/src/remote/activitypub/kernel/undo/block.ts
index c916a00737..9c277ed7d2 100644
--- a/src/remote/activitypub/kernel/undo/block.ts
+++ b/src/remote/activitypub/kernel/undo/block.ts
@@ -9,13 +9,14 @@ const logger = apLogger;
 
 export default async (actor: IRemoteUser, activity: IBlock): Promise<void> => {
 	const id = typeof activity.object == 'string' ? activity.object : activity.object.id;
+	if (id == null) throw 'missing id';
 
 	const uri = activity.id || activity;
 
 	logger.info(`UnBlock: ${uri}`);
 
 	if (!id.startsWith(config.url + '/')) {
-		return null;
+		return;
 	}
 
 	const blockee = await Users.findOne(id.split('/').pop());
diff --git a/src/remote/activitypub/kernel/undo/follow.ts b/src/remote/activitypub/kernel/undo/follow.ts
index cc63a740b1..ce84d0c791 100644
--- a/src/remote/activitypub/kernel/undo/follow.ts
+++ b/src/remote/activitypub/kernel/undo/follow.ts
@@ -7,9 +7,10 @@ import { Users, FollowRequests, Followings } from '../../../../models';
 
 export default async (actor: IRemoteUser, activity: IFollow): Promise<void> => {
 	const id = typeof activity.object == 'string' ? activity.object : activity.object.id;
+	if (id == null) throw 'missing id';
 
 	if (!id.startsWith(config.url + '/')) {
-		return null;
+		return;
 	}
 
 	const followee = await Users.findOne(id.split('/').pop());
diff --git a/src/remote/activitypub/kernel/undo/index.ts b/src/remote/activitypub/kernel/undo/index.ts
index 6376ab93a8..5f2e58c3bf 100644
--- a/src/remote/activitypub/kernel/undo/index.ts
+++ b/src/remote/activitypub/kernel/undo/index.ts
@@ -39,6 +39,4 @@ export default async (actor: IRemoteUser, activity: IUndo): Promise<void> => {
 			undoLike(actor, object as ILike);
 			break;
 	}
-
-	return null;
 };
diff --git a/src/remote/activitypub/kernel/undo/like.ts b/src/remote/activitypub/kernel/undo/like.ts
index f337a0173e..75879d697a 100644
--- a/src/remote/activitypub/kernel/undo/like.ts
+++ b/src/remote/activitypub/kernel/undo/like.ts
@@ -8,6 +8,7 @@ import { Notes } from '../../../../models';
  */
 export default async (actor: IRemoteUser, activity: ILike): Promise<void> => {
 	const id = typeof activity.object == 'string' ? activity.object : activity.object.id;
+	if (id == null) throw 'missing id';
 
 	const noteId = id.split('/').pop();
 
diff --git a/src/remote/activitypub/models/image.ts b/src/remote/activitypub/models/image.ts
index c9991dba3b..f8b35ea21c 100644
--- a/src/remote/activitypub/models/image.ts
+++ b/src/remote/activitypub/models/image.ts
@@ -5,6 +5,7 @@ import fetchMeta from '../../../misc/fetch-meta';
 import { apLogger } from '../logger';
 import { DriveFile } from '../../../models/entities/drive-file';
 import { DriveFiles } from '../../../models';
+import { ensure } from '../../../prelude/ensure';
 
 const logger = apLogger;
 
@@ -14,7 +15,7 @@ const logger = apLogger;
 export async function createImage(actor: IRemoteUser, value: any): Promise<DriveFile> {
 	// 投稿者が凍結されていたらスキップ
 	if (actor.isSuspended) {
-		return null;
+		throw new Error('actor has been suspended');
 	}
 
 	const image = await new Resolver().resolve(value) as any;
@@ -28,17 +29,7 @@ export async function createImage(actor: IRemoteUser, value: any): Promise<Drive
 	const instance = await fetchMeta();
 	const cache = instance.cacheRemoteFiles;
 
-	let file;
-	try {
-		file = await uploadFromUrl(image.url, actor, null, image.url, image.sensitive, false, !cache);
-	} catch (e) {
-		// 4xxの場合は添付されてなかったことにする
-		if (e >= 400 && e < 500) {
-			logger.warn(`Ignored image: ${image.url} - ${e}`);
-			return null;
-		}
-		throw e;
-	}
+	let file = await uploadFromUrl(image.url, actor, null, image.url, image.sensitive, false, !cache);
 
 	if (file.isLink) {
 		// URLが異なっている場合、同じ画像が以前に異なるURLで登録されていたということなので、
@@ -49,7 +40,7 @@ export async function createImage(actor: IRemoteUser, value: any): Promise<Drive
 				uri: image.url
 			});
 
-			file = DriveFiles.findOne(file.id);
+			file = await DriveFiles.findOne(file.id).then(ensure);
 		}
 	}
 
diff --git a/src/remote/activitypub/models/note.ts b/src/remote/activitypub/models/note.ts
index eb4175875d..78f5005953 100644
--- a/src/remote/activitypub/models/note.ts
+++ b/src/remote/activitypub/models/note.ts
@@ -21,6 +21,7 @@ import { IObject, INote } from '../type';
 import { Emoji } from '../../../models/entities/emoji';
 import { genId } from '../../../misc/gen-id';
 import fetchMeta from '../../../misc/fetch-meta';
+import { ensure } from '../../../prelude/ensure';
 
 const logger = apLogger;
 
@@ -29,13 +30,14 @@ const logger = apLogger;
  *
  * Misskeyに対象のNoteが登録されていればそれを返します。
  */
-export async function fetchNote(value: string | IObject, resolver?: Resolver): Promise<Note> {
+export async function fetchNote(value: string | IObject, resolver?: Resolver): Promise<Note | null> {
 	const uri = typeof value == 'string' ? value : value.id;
+	if (uri == null) throw 'missing uri';
 
 	// URIがこのサーバーを指しているならデータベースからフェッチ
 	if (uri.startsWith(config.url + '/')) {
 		const id = uri.split('/').pop();
-		return await Notes.findOne(id);
+		return await Notes.findOne(id).then(x => x || null);
 	}
 
 	//#region このサーバーに既に登録されていたらそれを返す
@@ -52,7 +54,7 @@ export async function fetchNote(value: string | IObject, resolver?: Resolver): P
 /**
  * Noteを作成します。
  */
-export async function createNote(value: any, resolver?: Resolver, silent = false): Promise<Note> {
+export async function createNote(value: any, resolver?: Resolver, silent = false): Promise<Note | null> {
 	if (resolver == null) resolver = new Resolver();
 
 	const object: any = await resolver.resolve(value);
@@ -65,7 +67,7 @@ export async function createNote(value: any, resolver?: Resolver, silent = false
 			value: value,
 			object: object
 		});
-		return null;
+		throw 'invalid note';
 	}
 
 	const note: INote = object;
@@ -75,11 +77,11 @@ export async function createNote(value: any, resolver?: Resolver, silent = false
 	logger.info(`Creating the Note: ${note.id}`);
 
 	// 投稿者をフェッチ
-	const actor = await resolvePerson(note.attributedTo, null, resolver) as IRemoteUser;
+	const actor = await resolvePerson(note.attributedTo, resolver) as IRemoteUser;
 
 	// 投稿者が凍結されていたらスキップ
 	if (actor.isSuspended) {
-		return null;
+		throw 'actor has been suspended';
 	}
 
 	//#region Visibility
@@ -95,9 +97,9 @@ export async function createNote(value: any, resolver?: Resolver, silent = false
 			visibility = 'followers';
 		} else {
 			visibility = 'specified';
-			visibleUsers = await Promise.all(note.to.map(uri => resolvePerson(uri, null, resolver)));
+			visibleUsers = await Promise.all(note.to.map(uri => resolvePerson(uri, resolver)));
 		}
-}
+	}
 	//#endergion
 
 	const apMentions = await extractMentionedUsers(actor, note.to, note.cc, resolver);
@@ -118,7 +120,7 @@ export async function createNote(value: any, resolver?: Resolver, silent = false
 		: [];
 
 	// リプライ
-	const reply: Note = note.inReplyTo
+	const reply: Note | undefined | null = note.inReplyTo
 		? await resolveNote(note.inReplyTo, resolver).catch(e => {
 			// 4xxの場合はリプライしてないことにする
 			if (e.statusCode >= 400 && e.statusCode < 500) {
@@ -131,7 +133,7 @@ export async function createNote(value: any, resolver?: Resolver, silent = false
 		: null;
 
 	// 引用
-	let quote: Note;
+	let quote: Note | undefined | null;
 
 	if (note._misskey_quote && typeof note._misskey_quote == 'string') {
 		quote = await resolveNote(note._misskey_quote).catch(e => {
@@ -152,7 +154,8 @@ export async function createNote(value: any, resolver?: Resolver, silent = false
 
 	// vote
 	if (reply && reply.hasPoll) {
-		const poll = await Polls.findOne({ noteId: reply.id });
+		const poll = await Polls.findOne({ noteId: reply.id }).then(ensure);
+
 		const tryCreateVote = async (name: string, index: number): Promise<null> => {
 			if (poll.expiresAt && Date.now() > new Date(poll.expiresAt).getTime()) {
 				logger.warn(`vote to expired poll from AP: actor=${actor.username}@${actor.host}, note=${note.id}, choice=${name}`);
@@ -180,7 +183,7 @@ export async function createNote(value: any, resolver?: Resolver, silent = false
 		}
 	}
 
-	const emojis = await extractEmojis(note.tag, actor.host).catch(e => {
+	const emojis = await extractEmojis(note.tag || [], actor.host).catch(e => {
 		logger.info(`extractEmojis: ${e}`);
 		return [] as Emoji[];
 	});
@@ -196,7 +199,7 @@ export async function createNote(value: any, resolver?: Resolver, silent = false
 	}
 
 	return await post(actor, {
-		createdAt: new Date(note.published),
+		createdAt: note.published ? new Date(note.published) : null,
 		files,
 		reply,
 		renote: quote,
@@ -223,8 +226,9 @@ export async function createNote(value: any, resolver?: Resolver, silent = false
  * Misskeyに対象のNoteが登録されていればそれを返し、そうでなければ
  * リモートサーバーからフェッチしてMisskeyに登録しそれを返します。
  */
-export async function resolveNote(value: string | IObject, resolver?: Resolver): Promise<Note> {
+export async function resolveNote(value: string | IObject, resolver?: Resolver): Promise<Note | null> {
 	const uri = typeof value == 'string' ? value : value.id;
+	if (uri == null) throw 'missing uri';
 
 	// ブロックしてたら中断
 	// TODO: いちいちデータベースにアクセスするのはコスト高そうなのでどっかにキャッシュしておく
@@ -244,75 +248,79 @@ export async function resolveNote(value: string | IObject, resolver?: Resolver):
 	// 添付されてきたNote Objectは偽装されている可能性があるため、常にuriを指定してサーバーフェッチを行う。
 	return await createNote(uri, resolver).catch(e => {
 		if (e.name === 'duplicated') {
-			return fetchNote(uri);
+			return fetchNote(uri).then(note => {
+				if (note == null) {
+					throw 'something happened';
+				} else {
+					return note;
+				}
+			});
 		} else {
 			throw e;
 		}
 	});
 }
 
-export async function extractEmojis(tags: ITag[], host: string) {
+export async function extractEmojis(tags: ITag[], host: string): Promise<Emoji[]> {
 	host = toPuny(host);
 
 	if (!tags) return [];
 
-	const eomjiTags = tags.filter(tag => tag.type === 'Emoji' && tag.icon && tag.icon.url);
+	const eomjiTags = tags.filter(tag => tag.type === 'Emoji' && tag.icon && tag.icon.url && tag.name);
 
-	return await Promise.all(
-		eomjiTags.map(async tag => {
-			const name = tag.name.replace(/^:/, '').replace(/:$/, '');
+	return await Promise.all(eomjiTags.map(async tag => {
+		const name = tag.name!.replace(/^:/, '').replace(/:$/, '');
 
-			const exists = await Emojis.findOne({
-				host,
-				name
-			});
+		const exists = await Emojis.findOne({
+			host,
+			name
+		});
 
-			if (exists) {
-				if ((tag.updated != null && exists.updatedAt == null)
-					|| (tag.id != null && exists.uri == null)
-					|| (tag.updated != null && exists.updatedAt != null && new Date(tag.updated) > exists.updatedAt)
-				) {
-					await Emojis.update({
-						host,
-						name,
-					}, {
-						uri: tag.id,
-						url: tag.icon.url,
-						updatedAt: new Date(tag.updated),
-					});
+		if (exists) {
+			if ((tag.updated != null && exists.updatedAt == null)
+				|| (tag.id != null && exists.uri == null)
+				|| (tag.updated != null && exists.updatedAt != null && new Date(tag.updated) > exists.updatedAt)
+			) {
+				await Emojis.update({
+					host,
+					name,
+				}, {
+					uri: tag.id,
+					url: tag.icon!.url,
+					updatedAt: new Date(tag.updated!),
+				});
 
-					return await Emojis.findOne({
-						host,
-						name
-					});
-				}
-
-				return exists;
+				return await Emojis.findOne({
+					host,
+					name
+				}) as Emoji;
 			}
 
-			logger.info(`register emoji host=${host}, name=${name}`);
+			return exists;
+		}
 
-			return await Emojis.save({
-				id: genId(),
-				host,
-				name,
-				uri: tag.id,
-				url: tag.icon.url,
-				updatedAt: tag.updated ? new Date(tag.updated) : undefined,
-				aliases: []
-			} as Emoji);
-		})
-	);
+		logger.info(`register emoji host=${host}, name=${name}`);
+
+		return await Emojis.save({
+			id: genId(),
+			host,
+			name,
+			uri: tag.id,
+			url: tag.icon!.url,
+			updatedAt: tag.updated ? new Date(tag.updated) : undefined,
+			aliases: []
+		} as Partial<Emoji>);
+	}));
 }
 
 async function extractMentionedUsers(actor: IRemoteUser, to: string[], cc: string[], resolver: Resolver) {
 	const ignoreUris = ['https://www.w3.org/ns/activitystreams#Public', `${actor.uri}/followers`];
 	const uris = difference(unique(concat([to || [], cc || []])), ignoreUris);
 
-	const limit = promiseLimit(2);
+	const limit = promiseLimit<User | null>(2);
 	const users = await Promise.all(
-		uris.map(uri => limit(() => resolvePerson(uri, null, resolver).catch(() => null)) as Promise<User>)
+		uris.map(uri => limit(() => resolvePerson(uri, resolver).catch(() => null)) as Promise<User | null>)
 	);
 
-	return users.filter(x => x != null);
+	return users.filter(x => x != null) as User[];
 }
diff --git a/src/remote/activitypub/models/person.ts b/src/remote/activitypub/models/person.ts
index e7021956de..9465cf0cd0 100644
--- a/src/remote/activitypub/models/person.ts
+++ b/src/remote/activitypub/models/person.ts
@@ -26,6 +26,7 @@ import { toPuny } from '../../../misc/convert-host';
 import { UserProfile } from '../../../models/entities/user-profile';
 import { validActor } from '../../../remote/activitypub/type';
 import { getConnection } from 'typeorm';
+import { ensure } from '../../../prelude/ensure';
 const logger = apLogger;
 
 /**
@@ -86,13 +87,13 @@ function validatePerson(x: any, uri: string) {
  *
  * Misskeyに対象のPersonが登録されていればそれを返します。
  */
-export async function fetchPerson(uri: string, resolver?: Resolver): Promise<User> {
+export async function fetchPerson(uri: string, resolver?: Resolver): Promise<User | null> {
 	if (typeof uri !== 'string') throw 'uri is not string';
 
 	// URIがこのサーバーを指しているならデータベースからフェッチ
 	if (uri.startsWith(config.url + '/')) {
 		const id = uri.split('/').pop();
-		return await Users.findOne(id);
+		return await Users.findOne(id).then(x => x || null);
 	}
 
 	//#region このサーバーに既に登録されていたらそれを返す
@@ -128,7 +129,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us
 
 	const host = toPuny(new URL(object.id).hostname);
 
-	const { fields } = analyzeAttachments(person.attachment);
+	const { fields } = analyzeAttachments(person.attachment || []);
 
 	const tags = extractHashtags(person.tag).map(tag => tag.toLowerCase());
 
@@ -161,7 +162,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us
 
 			await transactionalEntityManager.save(new UserProfile({
 				userId: user.id,
-				description: fromHtml(person.summary),
+				description: person.summary ? fromHtml(person.summary) : null,
 				url: person.url,
 				fields,
 				userHost: host
@@ -189,20 +190,20 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us
 		instanceChart.newUser(i.host);
 	});
 
-	usersChart.update(user, true);
+	usersChart.update(user!, true);
 
 	// ハッシュタグ更新
-	for (const tag of tags) updateHashtag(user, tag, true, true);
-	for (const tag of (user.tags || []).filter(x => !tags.includes(x))) updateHashtag(user, tag, true, false);
+	for (const tag of tags) updateHashtag(user!, tag, true, true);
+	for (const tag of (user!.tags || []).filter(x => !tags.includes(x))) updateHashtag(user!, tag, true, false);
 
 	//#region アイコンとヘッダー画像をフェッチ
-	const [avatar, banner] = (await Promise.all<DriveFile>([
+	const [avatar, banner] = (await Promise.all<DriveFile | null>([
 		person.icon,
 		person.image
 	].map(img =>
 		img == null
 			? Promise.resolve(null)
-			: resolveImage(user, img).catch(() => null)
+			: resolveImage(user!, img).catch(() => null)
 	)));
 
 	const avatarId = avatar ? avatar.id : null;
@@ -210,9 +211,9 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us
 	const avatarUrl = avatar ? DriveFiles.getPublicUrl(avatar) : null;
 	const bannerUrl = banner ? DriveFiles.getPublicUrl(banner) : null;
 	const avatarColor = avatar && avatar.properties.avgColor ? avatar.properties.avgColor : null;
-	const bannerColor = banner && avatar.properties.avgColor ? banner.properties.avgColor : null;
+	const bannerColor = banner && banner.properties.avgColor ? banner.properties.avgColor : null;
 
-	await Users.update(user.id, {
+	await Users.update(user!.id, {
 		avatarId,
 		bannerId,
 		avatarUrl,
@@ -221,30 +222,30 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us
 		bannerColor
 	});
 
-	user.avatarId = avatarId;
-	user.bannerId = bannerId;
-	user.avatarUrl = avatarUrl;
-	user.bannerUrl = bannerUrl;
-	user.avatarColor = avatarColor;
-	user.bannerColor = bannerColor;
+	user!.avatarId = avatarId;
+	user!.bannerId = bannerId;
+	user!.avatarUrl = avatarUrl;
+	user!.bannerUrl = bannerUrl;
+	user!.avatarColor = avatarColor;
+	user!.bannerColor = bannerColor;
 	//#endregion
 
 	//#region カスタム絵文字取得
-	const emojis = await extractEmojis(person.tag, host).catch(e => {
+	const emojis = await extractEmojis(person.tag || [], host).catch(e => {
 		logger.info(`extractEmojis: ${e}`);
 		return [] as Emoji[];
 	});
 
 	const emojiNames = emojis.map(emoji => emoji.name);
 
-	await Users.update(user.id, {
+	await Users.update(user!.id, {
 		emojis: emojiNames
 	});
 	//#endregion
 
-	await updateFeatured(user.id).catch(err => logger.error(err));
+	await updateFeatured(user!.id).catch(err => logger.error(err));
 
-	return user;
+	return user!;
 }
 
 /**
@@ -254,7 +255,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise<Us
  * @param resolver Resolver
  * @param hint Hint of Person object (この値が正当なPersonの場合、Remote resolveをせずに更新に利用します)
  */
-export async function updatePerson(uri: string, resolver?: Resolver, hint?: object): Promise<void> {
+export async function updatePerson(uri: string, resolver?: Resolver | null, hint?: object): Promise<void> {
 	if (typeof uri !== 'string') throw 'uri is not string';
 
 	// URIがこのサーバーを指しているならスキップ
@@ -290,7 +291,7 @@ export async function updatePerson(uri: string, resolver?: Resolver, hint?: obje
 	logger.info(`Updating the Person: ${person.id}`);
 
 	// アイコンとヘッダー画像をフェッチ
-	const [avatar, banner] = (await Promise.all<DriveFile>([
+	const [avatar, banner] = (await Promise.all<DriveFile | null>([
 		person.icon,
 		person.image
 	].map(img =>
@@ -300,14 +301,14 @@ export async function updatePerson(uri: string, resolver?: Resolver, hint?: obje
 	)));
 
 	// カスタム絵文字取得
-	const emojis = await extractEmojis(person.tag, exist.host).catch(e => {
+	const emojis = await extractEmojis(person.tag || [], exist.host).catch(e => {
 		logger.info(`extractEmojis: ${e}`);
 		return [] as Emoji[];
 	});
 
 	const emojiNames = emojis.map(emoji => emoji.name);
 
-	const { fields, services } = analyzeAttachments(person.attachment);
+	const { fields, services } = analyzeAttachments(person.attachment || []);
 
 	const tags = extractHashtags(person.tag).map(tag => tag.toLowerCase());
 
@@ -317,7 +318,7 @@ export async function updatePerson(uri: string, resolver?: Resolver, hint?: obje
 		sharedInbox: person.sharedInbox || (person.endpoints ? person.endpoints.sharedInbox : undefined),
 		featured: person.featured,
 		emojis: emojiNames,
-		description: fromHtml(person.summary),
+		description: person.summary ? fromHtml(person.summary) : null,
 		name: person.name,
 		url: person.url,
 		endpoints: person.endpoints,
@@ -326,7 +327,6 @@ export async function updatePerson(uri: string, resolver?: Resolver, hint?: obje
 		isBot: object.type == 'Service',
 		isCat: (person as any).isCat === true,
 		isLocked: person.manuallyApprovesFollowers,
-		createdAt: new Date(Date.parse(person.published)) || null,
 	} as Partial<User>;
 
 	if (avatar) {
@@ -379,7 +379,7 @@ export async function updatePerson(uri: string, resolver?: Resolver, hint?: obje
  * Misskeyに対象のPersonが登録されていればそれを返し、そうでなければ
  * リモートサーバーからフェッチしてMisskeyに登録しそれを返します。
  */
-export async function resolvePerson(uri: string, verifier?: string, resolver?: Resolver): Promise<User> {
+export async function resolvePerson(uri: string, resolver?: Resolver): Promise<User> {
 	if (typeof uri !== 'string') throw 'uri is not string';
 
 	//#region このサーバーに既に登録されていたらそれを返す
@@ -439,21 +439,24 @@ export function analyzeAttachments(attachments: ITag[]) {
 	}[] = [];
 	const services: { [x: string]: any } = {};
 
-	if (Array.isArray(attachments))
-		for (const attachment of attachments.filter(isPropertyValue))
-			if (isPropertyValue(attachment.identifier))
-				addService(services, attachment.identifier);
-			else
+	if (Array.isArray(attachments)) {
+		for (const attachment of attachments.filter(isPropertyValue)) {
+			if (isPropertyValue(attachment.identifier!)) {
+				addService(services, attachment.identifier!);
+			} else {
 				fields.push({
-					name: attachment.name,
-					value: fromHtml(attachment.value)
+					name: attachment.name!,
+					value: fromHtml(attachment.value!)
 				});
+			}
+		}
+	}
 
 	return { fields, services };
 }
 
 export async function updateFeatured(userId: User['id']) {
-	const user = await Users.findOne(userId);
+	const user = await Users.findOne(userId).then(ensure);
 	if (!Users.isRemoteUser(user)) return;
 	if (!user.featured) return;
 
@@ -471,18 +474,18 @@ export async function updateFeatured(userId: User['id']) {
 	if (!Array.isArray(items)) throw new Error(`Collection items is not an array`);
 
 	// Resolve and regist Notes
-	const limit = promiseLimit(2);
+	const limit = promiseLimit<Note | null>(2);
 	const featuredNotes = await Promise.all(items
 		.filter(item => item.type === 'Note')
 		.slice(0, 5)
-		.map(item => limit(() => resolveNote(item, resolver)) as Promise<Note>));
+		.map(item => limit(() => resolveNote(item, resolver))));
 
 	for (const note of featuredNotes.filter(note => note != null)) {
 		UserNotePinings.save({
 			id: genId(),
 			createdAt: new Date(),
 			userId: user.id,
-			noteId: note.id
+			noteId: note!.id
 		} as UserNotePining);
 	}
 }
diff --git a/src/remote/activitypub/models/question.ts b/src/remote/activitypub/models/question.ts
index 2ff8e21ab5..708cdc2a66 100644
--- a/src/remote/activitypub/models/question.ts
+++ b/src/remote/activitypub/models/question.ts
@@ -14,10 +14,10 @@ export async function extractPollFromQuestion(source: string | IQuestion): Promi
 		throw 'invalid question';
 	}
 
-	const choices = question[multiple ? 'anyOf' : 'oneOf']
-		.map((x, i) => x.name);
+	const choices = question[multiple ? 'anyOf' : 'oneOf']!
+		.map((x, i) => x.name!);
 
-	const votes = question[multiple ? 'anyOf' : 'oneOf']
+	const votes = question[multiple ? 'anyOf' : 'oneOf']!
 		.map((x, i) => x.replies && x.replies.totalItems || x._misskey_votes || 0);
 
 	return {
@@ -60,7 +60,7 @@ export async function updateQuestion(value: any) {
 
 	for (const choice of poll.choices) {
 		const oldCount = poll.votes[poll.choices.indexOf(choice)];
-		const newCount = apChoices.filter(ap => ap.name === choice)[0].replies.totalItems;
+		const newCount = apChoices!.filter(ap => ap.name === choice)[0].replies!.totalItems;
 
 		if (oldCount != newCount) {
 			changed = true;
diff --git a/src/remote/activitypub/models/tag.ts b/src/remote/activitypub/models/tag.ts
index 0a1e6e29f9..8d2008d1d9 100644
--- a/src/remote/activitypub/models/tag.ts
+++ b/src/remote/activitypub/models/tag.ts
@@ -14,13 +14,13 @@ export type ITag = {
 	identifier?: IIdentifier;
 };
 
-export function extractHashtags(tags: ITag[]) {
-	if (!tags) return [];
+export function extractHashtags(tags: ITag[] | null | undefined): string[] {
+	if (tags == null) return [];
 
 	const hashtags = tags.filter(tag => tag.type === 'Hashtag' && typeof tag.name == 'string');
 
 	return hashtags.map(tag => {
-		const m = tag.name.match(/^#(.+)/);
+		const m = tag.name ? tag.name.match(/^#(.+)/) : null;
 		return m ? m[1] : null;
-	}).filter(x => x != null);
+	}).filter(x => x != null) as string[];
 }
diff --git a/src/remote/activitypub/renderer/block.ts b/src/remote/activitypub/renderer/block.ts
index 946c45a813..c29a9aea82 100644
--- a/src/remote/activitypub/renderer/block.ts
+++ b/src/remote/activitypub/renderer/block.ts
@@ -1,7 +1,7 @@
 import config from '../../../config';
 import { ILocalUser, IRemoteUser } from '../../../models/entities/user';
 
-export default (blocker?: ILocalUser, blockee?: IRemoteUser) => ({
+export default (blocker: ILocalUser, blockee: IRemoteUser) => ({
 	type: 'Block',
 	actor: `${config.url}/users/${blocker.id}`,
 	object: blockee.uri
diff --git a/src/remote/activitypub/renderer/follow-user.ts b/src/remote/activitypub/renderer/follow-user.ts
index 9446be3c86..6d354803e5 100644
--- a/src/remote/activitypub/renderer/follow-user.ts
+++ b/src/remote/activitypub/renderer/follow-user.ts
@@ -1,12 +1,13 @@
 import config from '../../../config';
 import { Users } from '../../../models';
 import { User } from '../../../models/entities/user';
+import { ensure } from '../../../prelude/ensure';
 
 /**
  * Convert (local|remote)(Follower|Followee)ID to URL
  * @param id Follower|Followee ID
  */
 export default async function renderFollowUser(id: User['id']): Promise<any> {
-	const user = await Users.findOne(id);
+	const user = await Users.findOne(id).then(ensure);
 	return Users.isLocalUser(user) ? `${config.url}/users/${user.id}` : user.uri;
 }
diff --git a/src/remote/activitypub/renderer/note.ts b/src/remote/activitypub/renderer/note.ts
index 58ee4fb52c..c66af2667b 100644
--- a/src/remote/activitypub/renderer/note.ts
+++ b/src/remote/activitypub/renderer/note.ts
@@ -10,6 +10,7 @@ import { DriveFiles, Notes, Users, Emojis, Polls } from '../../../models';
 import { In } from 'typeorm';
 import { Emoji } from '../../../models/entities/emoji';
 import { Poll } from '../../../models/entities/poll';
+import { ensure } from '../../../prelude/ensure';
 
 export default async function renderNote(note: Note, dive = true): Promise<any> {
 	const promisedFiles: Promise<DriveFile[]> = note.fileIds.length > 0
@@ -17,15 +18,15 @@ export default async function renderNote(note: Note, dive = true): Promise<any>
 		: Promise.resolve([]);
 
 	let inReplyTo;
-	let inReplyToNote: Note;
+	let inReplyToNote: Note | undefined;
 
 	if (note.replyId) {
 		inReplyToNote = await Notes.findOne(note.replyId);
 
-		if (inReplyToNote !== null) {
+		if (inReplyToNote != null) {
 			const inReplyToUser = await Users.findOne(inReplyToNote.userId);
 
-			if (inReplyToUser !== null) {
+			if (inReplyToUser != null) {
 				if (inReplyToNote.uri) {
 					inReplyTo = inReplyToNote.uri;
 				} else {
@@ -51,9 +52,7 @@ export default async function renderNote(note: Note, dive = true): Promise<any>
 		}
 	}
 
-	const user = await Users.findOne({
-		id: note.userId
-	});
+	const user = await Users.findOne(note.userId).then(ensure);
 
 	const attributedTo = `${config.url}/users/${user.id}`;
 
@@ -85,13 +84,13 @@ export default async function renderNote(note: Note, dive = true): Promise<any>
 	const files = await promisedFiles;
 
 	let text = note.text;
-	let poll: Poll;
+	let poll: Poll | undefined;
 
 	if (note.hasPoll) {
 		poll = await Polls.findOne({ noteId: note.id });
 	}
 
-	let question: string;
+	let question: string | undefined;
 	if (poll) {
 		if (text == null) text = '';
 		const url = `${config.url}/notes/${note.id}`;
@@ -144,7 +143,7 @@ export default async function renderNote(note: Note, dive = true): Promise<any>
 			name: text,
 			replies: {
 				type: 'Collection',
-				totalItems: poll.votes[i]
+				totalItems: poll!.votes[i]
 			}
 		}))
 	} : {};
@@ -179,5 +178,5 @@ export async function getEmojis(names: string[]): Promise<Emoji[]> {
 		}))
 	);
 
-	return emojis.filter(emoji => emoji != null);
+	return emojis.filter(emoji => emoji != null) as Emoji[];
 }
diff --git a/src/remote/activitypub/renderer/ordered-collection-page.ts b/src/remote/activitypub/renderer/ordered-collection-page.ts
index 83af07870e..2433358646 100644
--- a/src/remote/activitypub/renderer/ordered-collection-page.ts
+++ b/src/remote/activitypub/renderer/ordered-collection-page.ts
@@ -7,7 +7,7 @@
  * @param prev URL of prev page (optional)
  * @param next URL of next page (optional)
  */
-export default function(id: string, totalItems: any, orderedItems: any, partOf: string, prev: string, next: string) {
+export default function(id: string, totalItems: any, orderedItems: any, partOf: string, prev?: string, next?: string) {
 	const page = {
 		id,
 		partOf,
diff --git a/src/remote/activitypub/renderer/person.ts b/src/remote/activitypub/renderer/person.ts
index e561e47c68..3fb164ef4e 100644
--- a/src/remote/activitypub/renderer/person.ts
+++ b/src/remote/activitypub/renderer/person.ts
@@ -9,14 +9,15 @@ import renderEmoji from './emoji';
 import { IIdentifier } from '../models/identifier';
 import renderHashtag from './hashtag';
 import { DriveFiles, UserProfiles, UserKeypairs } from '../../../models';
+import { ensure } from '../../../prelude/ensure';
 
 export async function renderPerson(user: ILocalUser) {
 	const id = `${config.url}/users/${user.id}`;
 
 	const [avatar, banner, profile] = await Promise.all([
-		DriveFiles.findOne(user.avatarId),
-		DriveFiles.findOne(user.bannerId),
-		UserProfiles.findOne({ userId: user.id })
+		user.avatarId ? DriveFiles.findOne(user.avatarId) : Promise.resolve(undefined),
+		user.bannerId ? DriveFiles.findOne(user.bannerId) : Promise.resolve(undefined),
+		UserProfiles.findOne({ userId: user.id }).then(ensure)
 	]);
 
 	const attachment: {
@@ -76,9 +77,7 @@ export async function renderPerson(user: ILocalUser) {
 		...hashtagTags,
 	];
 
-	const keypair = await UserKeypairs.findOne({
-		userId: user.id
-	});
+	const keypair = await UserKeypairs.findOne(user.id).then(ensure);
 
 	return {
 		type: user.isBot ? 'Service' : 'Person',
@@ -94,8 +93,8 @@ export async function renderPerson(user: ILocalUser) {
 		preferredUsername: user.username,
 		name: user.name,
 		summary: toHtml(parse(profile.description)),
-		icon: user.avatarId && renderImage(avatar),
-		image: user.bannerId && renderImage(banner),
+		icon: avatar ? renderImage(avatar) : null,
+		image: banner ? renderImage(banner) : null,
 		tag,
 		manuallyApprovesFollowers: user.isLocked,
 		publicKey: renderKey(user, keypair),
diff --git a/src/remote/activitypub/request.ts b/src/remote/activitypub/request.ts
index 8aca5e8102..7dc48c15e3 100644
--- a/src/remote/activitypub/request.ts
+++ b/src/remote/activitypub/request.ts
@@ -12,6 +12,7 @@ import { apLogger } from './logger';
 import { UserKeypairs } from '../../models';
 import fetchMeta from '../../misc/fetch-meta';
 import { toPuny } from '../../misc/convert-host';
+import { ensure } from '../../prelude/ensure';
 
 export const logger = apLogger.createSubLogger('deliver');
 
@@ -38,7 +39,7 @@ export default async (user: ILocalUser, url: string, object: any) => {
 
 	const keypair = await UserKeypairs.findOne({
 		userId: user.id
-	});
+	}).then(ensure);
 
 	const _ = new Promise((resolve, reject) => {
 		const req = request({
@@ -56,7 +57,7 @@ export default async (user: ILocalUser, url: string, object: any) => {
 				'Digest': `SHA-256=${hash}`
 			}
 		}, res => {
-			if (res.statusCode >= 400) {
+			if (res.statusCode! >= 400) {
 				logger.warn(`${url} --> ${res.statusCode}`);
 				reject(res);
 			} else {
@@ -73,7 +74,7 @@ export default async (user: ILocalUser, url: string, object: any) => {
 		});
 
 		// Signature: Signature ... => Signature: ...
-		let sig = req.getHeader('Signature').toString();
+		let sig = req.getHeader('Signature')!.toString();
 		sig = sig.replace(/^Signature /, '');
 		req.setHeader('Signature', sig);
 
@@ -112,7 +113,7 @@ async function resolveAddr(domain: string) {
 
 function resolveAddrInner(domain: string, options: IRunOptions = {}): Promise<string> {
 	return new Promise((res, rej) => {
-		lookup(domain, options, (error: any, address: string | string[]) => {
+		lookup(domain, options, (error, address) => {
 			if (error) return rej(error);
 			return res(Array.isArray(address) ? address[0] : address);
 		});
diff --git a/src/remote/resolve-user.ts b/src/remote/resolve-user.ts
index 6a8ce45c91..9b518f5e81 100644
--- a/src/remote/resolve-user.ts
+++ b/src/remote/resolve-user.ts
@@ -10,18 +10,31 @@ import { toPuny } from '../misc/convert-host';
 
 const logger = remoteLogger.createSubLogger('resolve-user');
 
-export async function resolveUser(username: string, host: string, option?: any, resync = false): Promise<User> {
+export async function resolveUser(username: string, host: string | null, option?: any, resync = false): Promise<User> {
 	const usernameLower = username.toLowerCase();
-	host = toPuny(host);
 
 	if (host == null) {
 		logger.info(`return local user: ${usernameLower}`);
-		return await Users.findOne({ usernameLower, host: null });
+		return await Users.findOne({ usernameLower, host: null }).then(u => {
+			if (u == null) {
+				throw 'user not found';
+			} else {
+				return u;
+			}
+		});
 	}
 
+	host = toPuny(host);
+
 	if (config.host == host) {
 		logger.info(`return local user: ${usernameLower}`);
-		return await Users.findOne({ usernameLower, host: null });
+		return await Users.findOne({ usernameLower, host: null }).then(u => {
+			if (u == null) {
+				throw 'user not found';
+			} else {
+				return u;
+			}
+		});
 	}
 
 	const user = await Users.findOne({ usernameLower, host }, option);
@@ -63,7 +76,13 @@ export async function resolveUser(username: string, host: string, option?: any,
 		await updatePerson(self.href);
 
 		logger.info(`return resynced remote user: ${acctLower}`);
-		return await Users.findOne({ uri: self.href });
+		return await Users.findOne({ uri: self.href }).then(u => {
+			if (u == null) {
+				throw 'user not found';
+			} else {
+				return u;
+			}
+		});
 	}
 
 	logger.info(`return existing remote user: ${acctLower}`);
@@ -76,7 +95,7 @@ async function resolveSelf(acctLower: string) {
 		logger.error(`Failed to WebFinger for ${chalk.yellow(acctLower)}: ${ e.statusCode || e.message }`);
 		throw new Error(`Failed to WebFinger for ${acctLower}: ${ e.statusCode || e.message }`);
 	});
-	const self = finger.links.find(link => link.rel && link.rel.toLowerCase() === 'self');
+	const self = finger.links.find(link => link.rel != null && link.rel.toLowerCase() === 'self');
 	if (!self) {
 		logger.error(`Failed to WebFinger for ${chalk.yellow(acctLower)}: self link not found`);
 		throw new Error('self link not found');
diff --git a/src/remote/webfinger.ts b/src/remote/webfinger.ts
index 67535e37db..800673943b 100644
--- a/src/remote/webfinger.ts
+++ b/src/remote/webfinger.ts
@@ -5,7 +5,7 @@ import { query as urlQuery } from '../prelude/url';
 
 type ILink = {
 	href: string;
-	rel: string;
+	rel?: string;
 };
 
 type IWebFinger = {
diff --git a/src/server/activitypub.ts b/src/server/activitypub.ts
index 3b39977d47..12fccbfa7d 100644
--- a/src/server/activitypub.ts
+++ b/src/server/activitypub.ts
@@ -17,6 +17,7 @@ import { isSelfHost } from '../misc/convert-host';
 import { Notes, Users, Emojis, UserKeypairs, Polls } from '../models';
 import { ILocalUser, User } from '../models/entities/user';
 import { In } from 'typeorm';
+import { ensure } from '../prelude/ensure';
 
 // Init router
 const router = new Router();
@@ -123,8 +124,8 @@ router.get('/questions/:question', async (ctx, next) => {
 		return;
 	}
 
-	const user = await Users.findOne(pollNote.userId);
-	const poll = await Polls.findOne({ noteId: pollNote.id });
+	const user = await Users.findOne(pollNote.userId).then(ensure);
+	const poll = await Polls.findOne({ noteId: pollNote.id }).then(ensure);
 
 	ctx.body = renderActivity(await renderQuestion(user as ILocalUser, pollNote, poll));
 	setResponseType(ctx);
@@ -156,9 +157,7 @@ router.get('/users/:user/publickey', async ctx => {
 		return;
 	}
 
-	const keypair = await UserKeypairs.findOne({
-		userId: user.id
-	});
+	const keypair = await UserKeypairs.findOne(user.id).then(ensure);
 
 	if (Users.isLocalUser(user)) {
 		ctx.body = renderActivity(renderKey(user, keypair));
@@ -189,7 +188,7 @@ router.get('/users/:user', async (ctx, next) => {
 	const user = await Users.findOne({
 		id: userId,
 		host: null
-	});
+	}).then(ensure);
 
 	await userInfo(ctx, user);
 });
@@ -200,7 +199,7 @@ router.get('/@:user', async (ctx, next) => {
 	const user = await Users.findOne({
 		usernameLower: ctx.params.user.toLowerCase(),
 		host: null
-	});
+	}).then(ensure);
 
 	await userInfo(ctx, user);
 });
diff --git a/src/server/activitypub/featured.ts b/src/server/activitypub/featured.ts
index f43312d79a..86ec1000c7 100644
--- a/src/server/activitypub/featured.ts
+++ b/src/server/activitypub/featured.ts
@@ -5,6 +5,7 @@ import renderOrderedCollection from '../../remote/activitypub/renderer/ordered-c
 import { setResponseType } from '../activitypub';
 import renderNote from '../../remote/activitypub/renderer/note';
 import { Users, Notes, UserNotePinings } from '../../models';
+import { ensure } from '../../prelude/ensure';
 
 export default async (ctx: Router.IRouterContext) => {
 	const userId = ctx.params.user;
@@ -22,13 +23,14 @@ export default async (ctx: Router.IRouterContext) => {
 
 	const pinings = await UserNotePinings.find({ userId: user.id });
 
-	const pinnedNotes = await Promise.all(pinings.map(pining => Notes.findOne(pining.noteId)));
+	const pinnedNotes = await Promise.all(pinings.map(pining =>
+		Notes.findOne(pining.noteId).then(ensure)));
 
 	const renderedNotes = await Promise.all(pinnedNotes.map(note => renderNote(note)));
 
 	const rendered = renderOrderedCollection(
 		`${config.url}/users/${userId}/collections/featured`,
-		renderedNotes.length, null, null, renderedNotes
+		renderedNotes.length, undefined, undefined, renderedNotes
 	);
 
 	ctx.body = renderActivity(rendered);
diff --git a/src/server/activitypub/followers.ts b/src/server/activitypub/followers.ts
index 62c54399ed..e48dc57f7a 100644
--- a/src/server/activitypub/followers.ts
+++ b/src/server/activitypub/followers.ts
@@ -69,18 +69,18 @@ export default async (ctx: Router.IRouterContext) => {
 				cursor
 			})}`,
 			user.followersCount, renderedFollowers, partOf,
-			null,
+			undefined,
 			inStock ? `${partOf}?${url.query({
 				page: 'true',
 				cursor: followings[followings.length - 1].id
-			})}` : null
+			})}` : undefined
 		);
 
 		ctx.body = renderActivity(rendered);
 		setResponseType(ctx);
 	} else {
 		// index page
-		const rendered = renderOrderedCollection(partOf, user.followersCount, `${partOf}?page=true`, null);
+		const rendered = renderOrderedCollection(partOf, user.followersCount, `${partOf}?page=true`);
 		ctx.body = renderActivity(rendered);
 		ctx.set('Cache-Control', 'private, max-age=0, must-revalidate');
 		setResponseType(ctx);
diff --git a/src/server/activitypub/following.ts b/src/server/activitypub/following.ts
index 4894aac1f8..4a7314e0ce 100644
--- a/src/server/activitypub/following.ts
+++ b/src/server/activitypub/following.ts
@@ -70,18 +70,18 @@ export default async (ctx: Router.IRouterContext) => {
 				cursor
 			})}`,
 			user.followingCount, renderedFollowees, partOf,
-			null,
+			undefined,
 			inStock ? `${partOf}?${url.query({
 				page: 'true',
 				cursor: followings[followings.length - 1].id
-			})}` : null
+			})}` : undefined
 		);
 
 		ctx.body = renderActivity(rendered);
 		setResponseType(ctx);
 	} else {
 		// index page
-		const rendered = renderOrderedCollection(partOf, user.followingCount, `${partOf}?page=true`, null);
+		const rendered = renderOrderedCollection(partOf, user.followingCount, `${partOf}?page=true`);
 		ctx.body = renderActivity(rendered);
 		ctx.set('Cache-Control', 'private, max-age=0, must-revalidate');
 		setResponseType(ctx);
diff --git a/src/server/activitypub/outbox.ts b/src/server/activitypub/outbox.ts
index 377f43c986..118d8f00a9 100644
--- a/src/server/activitypub/outbox.ts
+++ b/src/server/activitypub/outbox.ts
@@ -15,6 +15,7 @@ import { Users, Notes } from '../../models';
 import { makePaginationQuery } from '../api/common/make-pagination-query';
 import { Brackets } from 'typeorm';
 import { Note } from '../../models/entities/note';
+import { ensure } from '../../prelude/ensure';
 
 export default async (ctx: Router.IRouterContext) => {
 	const userId = ctx.params.user;
@@ -73,11 +74,11 @@ export default async (ctx: Router.IRouterContext) => {
 			notes.length ? `${partOf}?${url.query({
 				page: 'true',
 				since_id: notes[0].id
-			})}` : null,
+			})}` : undefined,
 			notes.length ? `${partOf}?${url.query({
 				page: 'true',
 				until_id: notes[notes.length - 1].id
-			})}` : null
+			})}` : undefined
 		);
 
 		ctx.body = renderActivity(rendered);
@@ -99,9 +100,9 @@ export default async (ctx: Router.IRouterContext) => {
  * Pack Create<Note> or Announce Activity
  * @param note Note
  */
-export async function packActivity(note: Note): Promise<object> {
+export async function packActivity(note: Note): Promise<any> {
 	if (note.renoteId && note.text == null && !note.hasPoll && (note.fileIds == null || note.fileIds.length == 0)) {
-		const renote = await Notes.findOne(note.renoteId);
+		const renote = await Notes.findOne(note.renoteId).then(ensure);
 		return renderAnnounce(renote.uri ? renote.uri : `${config.url}/notes/${renote.id}`, note);
 	}
 
diff --git a/src/server/api/api-handler.ts b/src/server/api/api-handler.ts
index 827aecdf25..2de6994f32 100644
--- a/src/server/api/api-handler.ts
+++ b/src/server/api/api-handler.ts
@@ -15,11 +15,11 @@ export default (endpoint: IEndpoint, ctx: Koa.BaseContext) => new Promise((res)
 			ctx.status = x;
 			ctx.body = {
 				error: {
-					message: y.message,
-					code: y.code,
-					id: y.id,
-					kind: y.kind,
-					...(y.info ? { info: y.info } : {})
+					message: y!.message,
+					code: y!.code,
+					id: y!.id,
+					kind: y!.kind,
+					...(y!.info ? { info: y!.info } : {})
 				}
 			};
 		} else {
@@ -31,9 +31,9 @@ export default (endpoint: IEndpoint, ctx: Koa.BaseContext) => new Promise((res)
 	// Authentication
 	authenticate(body['i']).then(([user, app]) => {
 		// API invoking
-		call(endpoint.name, user, app, body, (ctx.req as any).file).then(res => {
+		call(endpoint.name, user, app, body, (ctx.req as any).file).then((res: any) => {
 			reply(res);
-		}).catch(e => {
+		}).catch((e: ApiError) => {
 			reply(e.httpStatusCode ? e.httpStatusCode : e.kind == 'client' ? 400 : 500, e);
 		});
 	}).catch(() => {
diff --git a/src/server/api/authenticate.ts b/src/server/api/authenticate.ts
index e293e3fed0..5c2b7e45cf 100644
--- a/src/server/api/authenticate.ts
+++ b/src/server/api/authenticate.ts
@@ -3,7 +3,7 @@ import { User } from '../../models/entities/user';
 import { App } from '../../models/entities/app';
 import { Users, AccessTokens, Apps } from '../../models';
 
-export default async (token: string): Promise<[User, App]> => {
+export default async (token: string): Promise<[User | null | undefined, App | null | undefined]> => {
 	if (token == null) {
 		return [null, null];
 	}
diff --git a/src/server/api/call.ts b/src/server/api/call.ts
index d72f2cc9e6..c79f8eef5d 100644
--- a/src/server/api/call.ts
+++ b/src/server/api/call.ts
@@ -12,7 +12,7 @@ const accessDenied = {
 	id: '56f35758-7dd5-468b-8439-5d6fb8ec9b8e'
 };
 
-export default async (endpoint: string, user: User, app: App, data: any, file?: any) => {
+export default async (endpoint: string, user: User | null | undefined, app: App | null | undefined, data: any, file?: any) => {
 	const isSecure = user != null && app == null;
 
 	const ep = endpoints.find(e => e.name === endpoint);
@@ -39,15 +39,15 @@ export default async (endpoint: string, user: User, app: App, data: any, file?:
 		});
 	}
 
-	if (ep.meta.requireCredential && user.isSuspended) {
+	if (ep.meta.requireCredential && user!.isSuspended) {
 		throw new ApiError(accessDenied, { reason: 'Your account has been suspended.' });
 	}
 
-	if (ep.meta.requireAdmin && !user.isAdmin) {
+	if (ep.meta.requireAdmin && !user!.isAdmin) {
 		throw new ApiError(accessDenied, { reason: 'You are not the admin.' });
 	}
 
-	if (ep.meta.requireModerator && !user.isAdmin && !user.isModerator) {
+	if (ep.meta.requireModerator && !user!.isAdmin && !user!.isModerator) {
 		throw new ApiError(accessDenied, { reason: 'You are not a moderator.' });
 	}
 
@@ -61,7 +61,7 @@ export default async (endpoint: string, user: User, app: App, data: any, file?:
 
 	if (ep.meta.requireCredential && ep.meta.limit) {
 		// Rate limit
-		await limiter(ep, user).catch(e => {
+		await limiter(ep, user!).catch(e => {
 			throw new ApiError({
 				message: 'Rate limit exceeded. Please try again later.',
 				code: 'RATE_LIMIT_EXCEEDED',
diff --git a/src/server/api/common/make-pagination-query.ts b/src/server/api/common/make-pagination-query.ts
index 0c859a4f8d..51c11e5dff 100644
--- a/src/server/api/common/make-pagination-query.ts
+++ b/src/server/api/common/make-pagination-query.ts
@@ -1,6 +1,6 @@
 import { SelectQueryBuilder } from 'typeorm';
 
-export function makePaginationQuery<T>(q: SelectQueryBuilder<T>, sinceId: string, untilId: string, sinceDate?: number, untilDate?: number) {
+export function makePaginationQuery<T>(q: SelectQueryBuilder<T>, sinceId?: string, untilId?: string, sinceDate?: number, untilDate?: number) {
 	if (sinceId && untilId) {
 		q.andWhere(`${q.alias}.id > :sinceId`, { sinceId: sinceId });
 		q.andWhere(`${q.alias}.id < :untilId`, { untilId: untilId });
diff --git a/src/server/api/define.ts b/src/server/api/define.ts
index a18419bcf6..990cbf2a86 100644
--- a/src/server/api/define.ts
+++ b/src/server/api/define.ts
@@ -5,9 +5,9 @@ import { ApiError } from './error';
 import { App } from '../../models/entities/app';
 
 type Params<T extends IEndpointMeta> = {
-	[P in keyof T['params']]: T['params'][P]['transform'] extends Function
-		? ReturnType<T['params'][P]['transform']>
-		: ReturnType<T['params'][P]['validator']['get']>[0];
+	[P in keyof T['params']]: NonNullable<T['params']>[P]['transform'] extends Function
+		? ReturnType<NonNullable<T['params']>[P]['transform']>
+		: ReturnType<NonNullable<T['params']>[P]['validator']['get']>[0];
 };
 
 export type Response = Record<string, any> | void;
@@ -34,11 +34,11 @@ export default function <T extends IEndpointMeta>(meta: T, cb: (params: Params<T
 	};
 }
 
-function getParams<T extends IEndpointMeta>(defs: T, params: any): [Params<T>, ApiError] {
+function getParams<T extends IEndpointMeta>(defs: T, params: any): [Params<T>, ApiError | null] {
 	if (defs.params == null) return [params, null];
 
 	const x: any = {};
-	let err: ApiError = null;
+	let err: ApiError | null = null;
 	Object.entries(defs.params).some(([k, def]) => {
 		const [v, e] = def.validator.get(params[k]);
 		if (e) {
diff --git a/src/server/api/endpoints/admin/abuse-user-reports.ts b/src/server/api/endpoints/admin/abuse-user-reports.ts
index 5c5a734c1d..63d1dd795c 100644
--- a/src/server/api/endpoints/admin/abuse-user-reports.ts
+++ b/src/server/api/endpoints/admin/abuse-user-reports.ts
@@ -29,7 +29,7 @@ export const meta = {
 export default define(meta, async (ps) => {
 	const query = makePaginationQuery(AbuseUserReports.createQueryBuilder('report'), ps.sinceId, ps.untilId);
 
-	const reports = await query.take(ps.limit).getMany();
+	const reports = await query.take(ps.limit!).getMany();
 
 	return await AbuseUserReports.packMany(reports);
 });
diff --git a/src/server/api/endpoints/admin/drive/files.ts b/src/server/api/endpoints/admin/drive/files.ts
index 1ccabc92d9..7c6672e6de 100644
--- a/src/server/api/endpoints/admin/drive/files.ts
+++ b/src/server/api/endpoints/admin/drive/files.ts
@@ -56,8 +56,8 @@ export default define(meta, async (ps, me) => {
 
 	const files = await DriveFiles.find({
 		where: q,
-		take: ps.limit,
-		order: sort[ps.sort] || sort[fallback],
+		take: ps.limit!,
+		order: sort[ps.sort!] || sort[fallback],
 		skip: ps.offset
 	});
 
diff --git a/src/server/api/endpoints/admin/emoji/list.ts b/src/server/api/endpoints/admin/emoji/list.ts
index 26385d4e23..cf73e4cc75 100644
--- a/src/server/api/endpoints/admin/emoji/list.ts
+++ b/src/server/api/endpoints/admin/emoji/list.ts
@@ -23,7 +23,7 @@ export const meta = {
 
 export default define(meta, async (ps) => {
 	const emojis = await Emojis.find({
-		host: toPuny(ps.host)
+		host: ps.host ? toPuny(ps.host) : null
 	});
 
 	return emojis.map(e => ({
diff --git a/src/server/api/endpoints/admin/federation/remove-all-following.ts b/src/server/api/endpoints/admin/federation/remove-all-following.ts
index fca76e7086..25aae6db88 100644
--- a/src/server/api/endpoints/admin/federation/remove-all-following.ts
+++ b/src/server/api/endpoints/admin/federation/remove-all-following.ts
@@ -2,6 +2,7 @@ import $ from 'cafy';
 import define from '../../../define';
 import deleteFollowing from '../../../../../services/following/delete';
 import { Followings, Users } from '../../../../../models';
+import { ensure } from '../../../../../prelude/ensure';
 
 export const meta = {
 	tags: ['admin'],
@@ -22,13 +23,11 @@ export default define(meta, async (ps, me) => {
 	});
 
 	const pairs = await Promise.all(followings.map(f => Promise.all([
-		Users.findOne(f.followerId),
-		Users.findOne(f.followeeId)
+		Users.findOne(f.followerId).then(ensure),
+		Users.findOne(f.followeeId).then(ensure)
 	])));
 
 	for (const pair of pairs) {
 		deleteFollowing(pair[0], pair[1]);
 	}
-
-	return;
 });
diff --git a/src/server/api/endpoints/admin/logs.ts b/src/server/api/endpoints/admin/logs.ts
index 907b1fdc14..e1419bdfe1 100644
--- a/src/server/api/endpoints/admin/logs.ts
+++ b/src/server/api/endpoints/admin/logs.ts
@@ -65,7 +65,7 @@ export default define(meta, async (ps) => {
 		}
 	}
 
-	const logs = await query.orderBy('log.createdAt', 'DESC').take(ps.limit).getMany();
+	const logs = await query.orderBy('log.createdAt', 'DESC').take(ps.limit!).getMany();
 
 	return logs;
 });
diff --git a/src/server/api/endpoints/admin/queue/jobs.ts b/src/server/api/endpoints/admin/queue/jobs.ts
index c2496d7ef7..4e47775692 100644
--- a/src/server/api/endpoints/admin/queue/jobs.ts
+++ b/src/server/api/endpoints/admin/queue/jobs.ts
@@ -28,9 +28,9 @@ export default define(meta, async (ps) => {
 	const queue =
 		ps.domain === 'deliver' ? deliverQueue :
 		ps.domain === 'inbox' ? inboxQueue :
-		null;
+		null as never;
 
-	const jobs = await queue.getJobs([ps.state], 0, ps.limit);
+	const jobs = await queue.getJobs([ps.state], 0, ps.limit!);
 
 	return jobs.map(job => ({
 		id: job.id,
diff --git a/src/server/api/endpoints/admin/show-users.ts b/src/server/api/endpoints/admin/show-users.ts
index 73976b9872..97760ae797 100644
--- a/src/server/api/endpoints/admin/show-users.ts
+++ b/src/server/api/endpoints/admin/show-users.ts
@@ -82,7 +82,7 @@ export default define(meta, async (ps, me) => {
 		default: query.orderBy('user.id', 'ASC'); break;
 	}
 
-	query.take(ps.limit);
+	query.take(ps.limit!);
 	query.skip(ps.offset);
 
 	const users = await query.getMany();
diff --git a/src/server/api/endpoints/admin/update-remote-user.ts b/src/server/api/endpoints/admin/update-remote-user.ts
index 0be9047d5a..f9716328d5 100644
--- a/src/server/api/endpoints/admin/update-remote-user.ts
+++ b/src/server/api/endpoints/admin/update-remote-user.ts
@@ -28,5 +28,5 @@ export const meta = {
 
 export default define(meta, async (ps) => {
 	const user = await getRemoteUser(ps.userId);
-	await updatePerson(user.uri);
+	await updatePerson(user.uri!);
 });
diff --git a/src/server/api/endpoints/ap/show.ts b/src/server/api/endpoints/ap/show.ts
index 35c5dd318d..1b992eeaa7 100644
--- a/src/server/api/endpoints/ap/show.ts
+++ b/src/server/api/endpoints/ap/show.ts
@@ -123,14 +123,14 @@ async function fetchAny(uri: string) {
 		const note = await createNote(object.id);
 		return {
 			type: 'Note',
-			object: await Notes.pack(note, null, { detail: true })
+			object: await Notes.pack(note!, null, { detail: true })
 		};
 	}
 
 	return null;
 }
 
-async function mergePack(user: User, note: Note) {
+async function mergePack(user: User | null | undefined, note: Note | null | undefined) {
 	if (user != null) {
 		return {
 			type: 'User',
diff --git a/src/server/api/endpoints/auth/accept.ts b/src/server/api/endpoints/auth/accept.ts
index 0baa6b111c..55898b59db 100644
--- a/src/server/api/endpoints/auth/accept.ts
+++ b/src/server/api/endpoints/auth/accept.ts
@@ -5,6 +5,7 @@ import define from '../../define';
 import { ApiError } from '../../error';
 import { AuthSessions, AccessTokens, Apps } from '../../../../models';
 import { genId } from '../../../../misc/gen-id';
+import { ensure } from '../../../../prelude/ensure';
 
 export const meta = {
 	tags: ['auth'],
@@ -48,7 +49,7 @@ export default define(meta, async (ps, user) => {
 
 	if (exist == null) {
 		// Lookup app
-		const app = await Apps.findOne(session.appId);
+		const app = await Apps.findOne(session.appId).then(ensure);
 
 		// Generate Hash
 		const sha256 = crypto.createHash('sha256');
diff --git a/src/server/api/endpoints/auth/session/userkey.ts b/src/server/api/endpoints/auth/session/userkey.ts
index 8524b96f94..7126ac52c1 100644
--- a/src/server/api/endpoints/auth/session/userkey.ts
+++ b/src/server/api/endpoints/auth/session/userkey.ts
@@ -2,6 +2,7 @@ import $ from 'cafy';
 import define from '../../../define';
 import { ApiError } from '../../../error';
 import { Apps, AuthSessions, AccessTokens, Users } from '../../../../../models';
+import { ensure } from '../../../../../prelude/ensure';
 
 export const meta = {
 	tags: ['auth'],
@@ -90,7 +91,7 @@ export default define(meta, async (ps) => {
 	const accessToken = await AccessTokens.findOne({
 		appId: app.id,
 		userId: session.userId
-	});
+	}).then(ensure);
 
 	// Delete session
 	AuthSessions.delete(session.id);
diff --git a/src/server/api/endpoints/blocking/list.ts b/src/server/api/endpoints/blocking/list.ts
index a078891ab0..97f353579d 100644
--- a/src/server/api/endpoints/blocking/list.ts
+++ b/src/server/api/endpoints/blocking/list.ts
@@ -44,7 +44,7 @@ export default define(meta, async (ps, me) => {
 		.andWhere(`blocking.blockerId = :meId`, { meId: me.id });
 
 	const blockings = await query
-		.take(ps.limit)
+		.take(ps.limit!)
 		.getMany();
 
 	return await Blockings.packMany(blockings, me);
diff --git a/src/server/api/endpoints/charts/active-users.ts b/src/server/api/endpoints/charts/active-users.ts
index 60fa72c5c7..f0349b17f3 100644
--- a/src/server/api/endpoints/charts/active-users.ts
+++ b/src/server/api/endpoints/charts/active-users.ts
@@ -33,5 +33,5 @@ export const meta = {
 };
 
 export default define(meta, async (ps) => {
-	return await activeUsersChart.getChart(ps.span as any, ps.limit);
+	return await activeUsersChart.getChart(ps.span as any, ps.limit!);
 });
diff --git a/src/server/api/endpoints/charts/drive.ts b/src/server/api/endpoints/charts/drive.ts
index a9676e1586..ae6d894407 100644
--- a/src/server/api/endpoints/charts/drive.ts
+++ b/src/server/api/endpoints/charts/drive.ts
@@ -33,5 +33,5 @@ export const meta = {
 };
 
 export default define(meta, async (ps) => {
-	return await driveChart.getChart(ps.span as any, ps.limit);
+	return await driveChart.getChart(ps.span as any, ps.limit!);
 });
diff --git a/src/server/api/endpoints/charts/federation.ts b/src/server/api/endpoints/charts/federation.ts
index 95f16c76a7..34e9bfee5f 100644
--- a/src/server/api/endpoints/charts/federation.ts
+++ b/src/server/api/endpoints/charts/federation.ts
@@ -33,5 +33,5 @@ export const meta = {
 };
 
 export default define(meta, async (ps) => {
-	return await federationChart.getChart(ps.span as any, ps.limit);
+	return await federationChart.getChart(ps.span as any, ps.limit!);
 });
diff --git a/src/server/api/endpoints/charts/hashtag.ts b/src/server/api/endpoints/charts/hashtag.ts
index a7ec12707e..eceb0b275c 100644
--- a/src/server/api/endpoints/charts/hashtag.ts
+++ b/src/server/api/endpoints/charts/hashtag.ts
@@ -40,5 +40,5 @@ export const meta = {
 };
 
 export default define(meta, async (ps) => {
-	return await hashtagChart.getChart(ps.span as any, ps.limit, ps.tag);
+	return await hashtagChart.getChart(ps.span as any, ps.limit!, ps.tag);
 });
diff --git a/src/server/api/endpoints/charts/instance.ts b/src/server/api/endpoints/charts/instance.ts
index cf3094f7e1..e99c17ae65 100644
--- a/src/server/api/endpoints/charts/instance.ts
+++ b/src/server/api/endpoints/charts/instance.ts
@@ -41,5 +41,5 @@ export const meta = {
 };
 
 export default define(meta, async (ps) => {
-	return await instanceChart.getChart(ps.span as any, ps.limit, ps.host);
+	return await instanceChart.getChart(ps.span as any, ps.limit!, ps.host);
 });
diff --git a/src/server/api/endpoints/charts/network.ts b/src/server/api/endpoints/charts/network.ts
index c0fcd95fe9..648588fbe5 100644
--- a/src/server/api/endpoints/charts/network.ts
+++ b/src/server/api/endpoints/charts/network.ts
@@ -33,5 +33,5 @@ export const meta = {
 };
 
 export default define(meta, async (ps) => {
-	return await networkChart.getChart(ps.span as any, ps.limit);
+	return await networkChart.getChart(ps.span as any, ps.limit!);
 });
diff --git a/src/server/api/endpoints/charts/notes.ts b/src/server/api/endpoints/charts/notes.ts
index 86f30e4b89..074c4978cd 100644
--- a/src/server/api/endpoints/charts/notes.ts
+++ b/src/server/api/endpoints/charts/notes.ts
@@ -33,5 +33,5 @@ export const meta = {
 };
 
 export default define(meta, async (ps) => {
-	return await notesChart.getChart(ps.span as any, ps.limit);
+	return await notesChart.getChart(ps.span as any, ps.limit!);
 });
diff --git a/src/server/api/endpoints/charts/user/drive.ts b/src/server/api/endpoints/charts/user/drive.ts
index e3696dfda1..918fb62c6a 100644
--- a/src/server/api/endpoints/charts/user/drive.ts
+++ b/src/server/api/endpoints/charts/user/drive.ts
@@ -42,5 +42,5 @@ export const meta = {
 };
 
 export default define(meta, async (ps) => {
-	return await perUserDriveChart.getChart(ps.span as any, ps.limit, ps.userId);
+	return await perUserDriveChart.getChart(ps.span as any, ps.limit!, ps.userId);
 });
diff --git a/src/server/api/endpoints/charts/user/following.ts b/src/server/api/endpoints/charts/user/following.ts
index 8feba0bd16..5d86e85d31 100644
--- a/src/server/api/endpoints/charts/user/following.ts
+++ b/src/server/api/endpoints/charts/user/following.ts
@@ -42,5 +42,5 @@ export const meta = {
 };
 
 export default define(meta, async (ps) => {
-	return await perUserFollowingChart.getChart(ps.span as any, ps.limit, ps.userId);
+	return await perUserFollowingChart.getChart(ps.span as any, ps.limit!, ps.userId);
 });
diff --git a/src/server/api/endpoints/charts/user/notes.ts b/src/server/api/endpoints/charts/user/notes.ts
index 8c1db54f76..d39a20df16 100644
--- a/src/server/api/endpoints/charts/user/notes.ts
+++ b/src/server/api/endpoints/charts/user/notes.ts
@@ -42,5 +42,5 @@ export const meta = {
 };
 
 export default define(meta, async (ps) => {
-	return await perUserNotesChart.getChart(ps.span as any, ps.limit, ps.userId);
+	return await perUserNotesChart.getChart(ps.span as any, ps.limit!, ps.userId);
 });
diff --git a/src/server/api/endpoints/charts/user/reactions.ts b/src/server/api/endpoints/charts/user/reactions.ts
index 7c9b2508ae..5b88a1d715 100644
--- a/src/server/api/endpoints/charts/user/reactions.ts
+++ b/src/server/api/endpoints/charts/user/reactions.ts
@@ -42,5 +42,5 @@ export const meta = {
 };
 
 export default define(meta, async (ps) => {
-	return await perUserReactionsChart.getChart(ps.span as any, ps.limit, ps.userId);
+	return await perUserReactionsChart.getChart(ps.span as any, ps.limit!, ps.userId);
 });
diff --git a/src/server/api/endpoints/charts/users.ts b/src/server/api/endpoints/charts/users.ts
index 3ed5e09349..17de5756da 100644
--- a/src/server/api/endpoints/charts/users.ts
+++ b/src/server/api/endpoints/charts/users.ts
@@ -33,5 +33,5 @@ export const meta = {
 };
 
 export default define(meta, async (ps) => {
-	return await usersChart.getChart(ps.span as any, ps.limit);
+	return await usersChart.getChart(ps.span as any, ps.limit!);
 });
diff --git a/src/server/api/endpoints/drive/files.ts b/src/server/api/endpoints/drive/files.ts
index 400b73d3b7..4e4db6c780 100644
--- a/src/server/api/endpoints/drive/files.ts
+++ b/src/server/api/endpoints/drive/files.ts
@@ -66,7 +66,7 @@ export default define(meta, async (ps, user) => {
 		}
 	}
 
-	const files = await query.take(ps.limit).getMany();
+	const files = await query.take(ps.limit!).getMany();
 
 	return await DriveFiles.packMany(files, { detail: false, self: true });
 });
diff --git a/src/server/api/endpoints/drive/files/create.ts b/src/server/api/endpoints/drive/files/create.ts
index 5702c70fc0..340a39a41c 100644
--- a/src/server/api/endpoints/drive/files/create.ts
+++ b/src/server/api/endpoints/drive/files/create.ts
@@ -92,6 +92,6 @@ export default define(meta, async (ps, user, app, file, cleanup) => {
 		apiLogger.error(e);
 		throw new ApiError();
 	} finally {
-		cleanup();
+		cleanup!();
 	}
 });
diff --git a/src/server/api/endpoints/drive/files/show.ts b/src/server/api/endpoints/drive/files/show.ts
index b516ec2df6..e8c0e683c9 100644
--- a/src/server/api/endpoints/drive/files/show.ts
+++ b/src/server/api/endpoints/drive/files/show.ts
@@ -63,7 +63,7 @@ export const meta = {
 };
 
 export default define(meta, async (ps, user) => {
-	let file: DriveFile;
+	let file: DriveFile | undefined;
 
 	if (ps.fileId) {
 		file = await DriveFiles.findOne(ps.fileId);
@@ -81,14 +81,14 @@ export default define(meta, async (ps, user) => {
 		throw new ApiError(meta.errors.fileIdOrUrlRequired);
 	}
 
-	if (!user.isAdmin && !user.isModerator && (file.userId !== user.id)) {
-		throw new ApiError(meta.errors.accessDenied);
-	}
-
 	if (file == null) {
 		throw new ApiError(meta.errors.noSuchFile);
 	}
 
+	if (!user.isAdmin && !user.isModerator && (file.userId !== user.id)) {
+		throw new ApiError(meta.errors.accessDenied);
+	}
+
 	return await DriveFiles.pack(file, {
 		detail: true,
 		self: true
diff --git a/src/server/api/endpoints/drive/folders.ts b/src/server/api/endpoints/drive/folders.ts
index f5c3816407..08ae2ff709 100644
--- a/src/server/api/endpoints/drive/folders.ts
+++ b/src/server/api/endpoints/drive/folders.ts
@@ -54,7 +54,7 @@ export default define(meta, async (ps, user) => {
 		query.andWhere('folder.parentId IS NULL');
 	}
 
-	const folders = await query.take(ps.limit).getMany();
+	const folders = await query.take(ps.limit!).getMany();
 
 	return await Promise.all(folders.map(folder => DriveFolders.pack(folder)));
 });
diff --git a/src/server/api/endpoints/drive/folders/update.ts b/src/server/api/endpoints/drive/folders/update.ts
index 90129bed63..7d3ece00a3 100644
--- a/src/server/api/endpoints/drive/folders/update.ts
+++ b/src/server/api/endpoints/drive/folders/update.ts
@@ -102,10 +102,10 @@ export default define(meta, async (ps, user) => {
 					id: folderId
 				});
 
-				if (folder2.id === folder.id) {
+				if (folder2!.id === folder!.id) {
 					return true;
-				} else if (folder2.parentId) {
-					return await checkCircle(folder2.parentId);
+				} else if (folder2!.parentId) {
+					return await checkCircle(folder2!.parentId);
 				} else {
 					return false;
 				}
diff --git a/src/server/api/endpoints/drive/stream.ts b/src/server/api/endpoints/drive/stream.ts
index 9a84627767..96d9f82421 100644
--- a/src/server/api/endpoints/drive/stream.ts
+++ b/src/server/api/endpoints/drive/stream.ts
@@ -50,7 +50,7 @@ export default define(meta, async (ps, user) => {
 		}
 	}
 
-	const files = await query.take(ps.limit).getMany();
+	const files = await query.take(ps.limit!).getMany();
 
 	return await DriveFiles.packMany(files, { detail: false, self: true });
 });
diff --git a/src/server/api/endpoints/federation/instances.ts b/src/server/api/endpoints/federation/instances.ts
index 1946d26dec..301338ed96 100644
--- a/src/server/api/endpoints/federation/instances.ts
+++ b/src/server/api/endpoints/federation/instances.ts
@@ -86,7 +86,7 @@ export default define(meta, async (ps, me) => {
 		}
 	}
 
-	const instances = await query.take(ps.limit).skip(ps.offset).getMany();
+	const instances = await query.take(ps.limit!).skip(ps.offset).getMany();
 
 	return instances;
 });
diff --git a/src/server/api/endpoints/games/reversi/games.ts b/src/server/api/endpoints/games/reversi/games.ts
index 07736e0424..7267157e0e 100644
--- a/src/server/api/endpoints/games/reversi/games.ts
+++ b/src/server/api/endpoints/games/reversi/games.ts
@@ -41,7 +41,7 @@ export default define(meta, async (ps, user) => {
 	}
 
 	// Fetch games
-	const games = await query.take(ps.limit).getMany();
+	const games = await query.take(ps.limit!).getMany();
 
 	return await Promise.all(games.map((g) => ReversiGames.pack(g, user, {
 		detail: false
diff --git a/src/server/api/endpoints/games/reversi/match.ts b/src/server/api/endpoints/games/reversi/match.ts
index e34d3c67f4..da367b5978 100644
--- a/src/server/api/endpoints/games/reversi/match.ts
+++ b/src/server/api/endpoints/games/reversi/match.ts
@@ -70,7 +70,7 @@ export default define(meta, async (ps, user) => {
 			map: eighteight.data,
 			bw: 'random',
 			isLlotheo: false
-		} as ReversiGame);
+		} as Partial<ReversiGame>);
 
 		publishReversiStream(exist.parentId, 'matched', await ReversiGames.pack(game, exist.parentId));
 
@@ -107,6 +107,6 @@ export default define(meta, async (ps, user) => {
 		publishReversiStream(child.id, 'invited', packed);
 		publishMainStream(child.id, 'reversiInvited', packed);
 
-		return null;
+		return;
 	}
 });
diff --git a/src/server/api/endpoints/hashtags/list.ts b/src/server/api/endpoints/hashtags/list.ts
index 7996c81669..2998bc1a13 100644
--- a/src/server/api/endpoints/hashtags/list.ts
+++ b/src/server/api/endpoints/hashtags/list.ts
@@ -86,7 +86,7 @@ export default define(meta, async (ps, me) => {
 		'tag.attachedRemoteUsersCount',
 	]);
 
-	const tags = await query.take(ps.limit).getMany();
+	const tags = await query.take(ps.limit!).getMany();
 
 	return tags;
 });
diff --git a/src/server/api/endpoints/hashtags/search.ts b/src/server/api/endpoints/hashtags/search.ts
index fd91a2ebcc..6a9a2df6ef 100644
--- a/src/server/api/endpoints/hashtags/search.ts
+++ b/src/server/api/endpoints/hashtags/search.ts
@@ -48,7 +48,7 @@ export default define(meta, async (ps) => {
 	const hashtags = await Hashtags.createQueryBuilder('tag')
 		.where('tag.name like :q', { q: ps.query.toLowerCase() + '%' })
 		.orderBy('tag.count', 'DESC')
-		.take(ps.limit)
+		.take(ps.limit!)
 		.skip(ps.offset)
 		.getMany();
 
diff --git a/src/server/api/endpoints/hashtags/users.ts b/src/server/api/endpoints/hashtags/users.ts
index 20cba96d0e..fa58f2f2c0 100644
--- a/src/server/api/endpoints/hashtags/users.ts
+++ b/src/server/api/endpoints/hashtags/users.ts
@@ -79,7 +79,7 @@ export default define(meta, async (ps, me) => {
 		case '-updatedAt': query.orderBy('user.updatedAt', 'ASC'); break;
 	}
 
-	const users = await query.take(ps.limit).getMany();
+	const users = await query.take(ps.limit!).getMany();
 
 	return await Users.packMany(users, me, { detail: true });
 });
diff --git a/src/server/api/endpoints/i/2fa/done.ts b/src/server/api/endpoints/i/2fa/done.ts
index edc7cefd26..e23678dcbb 100644
--- a/src/server/api/endpoints/i/2fa/done.ts
+++ b/src/server/api/endpoints/i/2fa/done.ts
@@ -2,6 +2,7 @@ import $ from 'cafy';
 import * as speakeasy from 'speakeasy';
 import define from '../../../define';
 import { UserProfiles } from '../../../../../models';
+import { ensure } from '../../../../../prelude/ensure';
 
 export const meta = {
 	requireCredential: true,
@@ -18,7 +19,7 @@ export const meta = {
 export default define(meta, async (ps, user) => {
 	const token = ps.token.replace(/\s/g, '');
 
-	const profile = await UserProfiles.findOne({ userId: user.id });
+	const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure);
 
 	if (profile.twoFactorTempSecret == null) {
 		throw new Error('二段階認証の設定が開始されていません');
diff --git a/src/server/api/endpoints/i/2fa/register.ts b/src/server/api/endpoints/i/2fa/register.ts
index db9a2fe944..76d79b3a49 100644
--- a/src/server/api/endpoints/i/2fa/register.ts
+++ b/src/server/api/endpoints/i/2fa/register.ts
@@ -5,6 +5,7 @@ import * as QRCode from 'qrcode';
 import config from '../../../../../config';
 import define from '../../../define';
 import { UserProfiles } from '../../../../../models';
+import { ensure } from '../../../../../prelude/ensure';
 
 export const meta = {
 	requireCredential: true,
@@ -19,10 +20,10 @@ export const meta = {
 };
 
 export default define(meta, async (ps, user) => {
-	const profile = await UserProfiles.findOne({ userId: user.id });
+	const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure);
 
 	// Compare password
-	const same = await bcrypt.compare(ps.password, profile.password);
+	const same = await bcrypt.compare(ps.password, profile.password!);
 
 	if (!same) {
 		throw new Error('incorrect password');
diff --git a/src/server/api/endpoints/i/2fa/unregister.ts b/src/server/api/endpoints/i/2fa/unregister.ts
index fa25b74391..9c7857e7ef 100644
--- a/src/server/api/endpoints/i/2fa/unregister.ts
+++ b/src/server/api/endpoints/i/2fa/unregister.ts
@@ -2,6 +2,7 @@ import $ from 'cafy';
 import * as bcrypt from 'bcryptjs';
 import define from '../../../define';
 import { UserProfiles } from '../../../../../models';
+import { ensure } from '../../../../../prelude/ensure';
 
 export const meta = {
 	requireCredential: true,
@@ -16,10 +17,10 @@ export const meta = {
 };
 
 export default define(meta, async (ps, user) => {
-	const profile = await UserProfiles.findOne({ userId: user.id });
+	const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure);
 
 	// Compare password
-	const same = await bcrypt.compare(ps.password, profile.password);
+	const same = await bcrypt.compare(ps.password, profile.password!);
 
 	if (!same) {
 		throw new Error('incorrect password');
diff --git a/src/server/api/endpoints/i/authorized-apps.ts b/src/server/api/endpoints/i/authorized-apps.ts
index ebf04fcb58..3e9fea19e2 100644
--- a/src/server/api/endpoints/i/authorized-apps.ts
+++ b/src/server/api/endpoints/i/authorized-apps.ts
@@ -31,7 +31,7 @@ export default define(meta, async (ps, user) => {
 		where: {
 			userId: user.id
 		},
-		take: ps.limit,
+		take: ps.limit!,
 		skip: ps.offset,
 		order: {
 			id: ps.sort == 'asc' ? 1 : -1
diff --git a/src/server/api/endpoints/i/change-password.ts b/src/server/api/endpoints/i/change-password.ts
index d0e0695e18..0dda125b9c 100644
--- a/src/server/api/endpoints/i/change-password.ts
+++ b/src/server/api/endpoints/i/change-password.ts
@@ -2,6 +2,7 @@ import $ from 'cafy';
 import * as bcrypt from 'bcryptjs';
 import define from '../../define';
 import { UserProfiles } from '../../../../models';
+import { ensure } from '../../../../prelude/ensure';
 
 export const meta = {
 	requireCredential: true,
@@ -20,10 +21,10 @@ export const meta = {
 };
 
 export default define(meta, async (ps, user) => {
-	const profile = await UserProfiles.findOne({ userId: user.id });
+	const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure);
 
 	// Compare password
-	const same = await bcrypt.compare(ps.currentPassword, profile.password);
+	const same = await bcrypt.compare(ps.currentPassword, profile.password!);
 
 	if (!same) {
 		throw new Error('incorrect password');
diff --git a/src/server/api/endpoints/i/delete-account.ts b/src/server/api/endpoints/i/delete-account.ts
index 7ef7aa5fac..389d0b3212 100644
--- a/src/server/api/endpoints/i/delete-account.ts
+++ b/src/server/api/endpoints/i/delete-account.ts
@@ -2,6 +2,7 @@ import $ from 'cafy';
 import * as bcrypt from 'bcryptjs';
 import define from '../../define';
 import { Users, UserProfiles } from '../../../../models';
+import { ensure } from '../../../../prelude/ensure';
 
 export const meta = {
 	requireCredential: true,
@@ -16,10 +17,10 @@ export const meta = {
 };
 
 export default define(meta, async (ps, user) => {
-	const profile = await UserProfiles.findOne({ userId: user.id });
+	const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure);
 
 	// Compare password
-	const same = await bcrypt.compare(ps.password, profile.password);
+	const same = await bcrypt.compare(ps.password, profile.password!);
 
 	if (!same) {
 		throw new Error('incorrect password');
diff --git a/src/server/api/endpoints/i/favorites.ts b/src/server/api/endpoints/i/favorites.ts
index d2d149b2d1..2c25250bea 100644
--- a/src/server/api/endpoints/i/favorites.ts
+++ b/src/server/api/endpoints/i/favorites.ts
@@ -38,7 +38,7 @@ export default define(meta, async (ps, user) => {
 		.leftJoinAndSelect('favorite.note', 'note');
 
 	const favorites = await query
-		.take(ps.limit)
+		.take(ps.limit!)
 		.getMany();
 
 	return await NoteFavorites.packMany(favorites, user);
diff --git a/src/server/api/endpoints/i/notifications.ts b/src/server/api/endpoints/i/notifications.ts
index 9b016e0a2d..56074c9d00 100644
--- a/src/server/api/endpoints/i/notifications.ts
+++ b/src/server/api/endpoints/i/notifications.ts
@@ -81,13 +81,13 @@ export default define(meta, async (ps, user) => {
 		query.setParameters(followingQuery.getParameters());
 	}
 
-	if (ps.includeTypes.length > 0) {
+	if (ps.includeTypes!.length > 0) {
 		query.andWhere(`notification.type IN (:...includeTypes)`, { includeTypes: ps.includeTypes });
-	} else if (ps.excludeTypes.length > 0) {
+	} else if (ps.excludeTypes!.length > 0) {
 		query.andWhere(`notification.type NOT IN (:...excludeTypes)`, { excludeTypes: ps.excludeTypes });
 	}
 
-	const notifications = await query.take(ps.limit).getMany();
+	const notifications = await query.take(ps.limit!).getMany();
 
 	// Mark all as read
 	if (notifications.length > 0 && ps.markAsRead) {
diff --git a/src/server/api/endpoints/i/regenerate-token.ts b/src/server/api/endpoints/i/regenerate-token.ts
index ec53bca979..56c0362c88 100644
--- a/src/server/api/endpoints/i/regenerate-token.ts
+++ b/src/server/api/endpoints/i/regenerate-token.ts
@@ -4,6 +4,7 @@ import { publishMainStream } from '../../../../services/stream';
 import generateUserToken from '../../common/generate-native-user-token';
 import define from '../../define';
 import { Users, UserProfiles } from '../../../../models';
+import { ensure } from '../../../../prelude/ensure';
 
 export const meta = {
 	requireCredential: true,
@@ -18,10 +19,10 @@ export const meta = {
 };
 
 export default define(meta, async (ps, user) => {
-	const profile = await UserProfiles.findOne({ userId: user.id });
+	const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure);
 
 	// Compare password
-	const same = await bcrypt.compare(ps.password, profile.password);
+	const same = await bcrypt.compare(ps.password, profile.password!);
 
 	if (!same) {
 		throw new Error('incorrect password');
diff --git a/src/server/api/endpoints/i/signin-history.ts b/src/server/api/endpoints/i/signin-history.ts
index e9ae19d734..74648951fd 100644
--- a/src/server/api/endpoints/i/signin-history.ts
+++ b/src/server/api/endpoints/i/signin-history.ts
@@ -29,7 +29,7 @@ export default define(meta, async (ps, user) => {
 	const query = makePaginationQuery(Signins.createQueryBuilder('signin'), ps.sinceId, ps.untilId)
 		.andWhere(`signin.userId = :meId`, { meId: user.id });
 
-	const history = await query.take(ps.limit).getMany();
+	const history = await query.take(ps.limit!).getMany();
 
 	return await Promise.all(history.map(record => Signins.pack(record)));
 });
diff --git a/src/server/api/endpoints/i/update-email.ts b/src/server/api/endpoints/i/update-email.ts
index d98f0d753e..8b05f3c8cb 100644
--- a/src/server/api/endpoints/i/update-email.ts
+++ b/src/server/api/endpoints/i/update-email.ts
@@ -9,6 +9,7 @@ import * as ms from 'ms';
 import * as bcrypt from 'bcryptjs';
 import { apiLogger } from '../../logger';
 import { Users, UserProfiles } from '../../../../models';
+import { ensure } from '../../../../prelude/ensure';
 
 export const meta = {
 	requireCredential: true,
@@ -32,10 +33,10 @@ export const meta = {
 };
 
 export default define(meta, async (ps, user) => {
-	const profile = await UserProfiles.findOne({ userId: user.id });
+	const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure);
 
 	// Compare password
-	const same = await bcrypt.compare(ps.password, profile.password);
+	const same = await bcrypt.compare(ps.password, profile.password!);
 
 	if (!same) {
 		throw new Error('incorrect password');
diff --git a/src/server/api/endpoints/i/update.ts b/src/server/api/endpoints/i/update.ts
index 3cb514d939..d06ab621c6 100644
--- a/src/server/api/endpoints/i/update.ts
+++ b/src/server/api/endpoints/i/update.ts
@@ -206,13 +206,13 @@ export default define(meta, async (ps, user, app) => {
 
 	if (updates.name != null) {
 		const tokens = parsePlain(updates.name);
-		emojis = emojis.concat(extractEmojis(tokens));
+		emojis = emojis.concat(extractEmojis(tokens!));
 	}
 
 	if (profile.description != null) {
 		const tokens = parse(profile.description);
-		emojis = emojis.concat(extractEmojis(tokens));
-		tags = extractHashtags(tokens).map(tag => tag.toLowerCase());
+		emojis = emojis.concat(extractEmojis(tokens!));
+		tags = extractHashtags(tokens!).map(tag => tag.toLowerCase());
 	}
 
 	updates.emojis = emojis;
diff --git a/src/server/api/endpoints/messaging/history.ts b/src/server/api/endpoints/messaging/history.ts
index c0aec61212..c12378eb7e 100644
--- a/src/server/api/endpoints/messaging/history.ts
+++ b/src/server/api/endpoints/messaging/history.ts
@@ -38,7 +38,7 @@ export default define(meta, async (ps, user) => {
 
 	const history: MessagingMessage[] = [];
 
-	for (let i = 0; i < ps.limit; i++) {
+	for (let i = 0; i < ps.limit!; i++) {
 		const found = history.map(m => (m.userId === user.id) ? m.recipientId : m.userId);
 
 		const query = MessagingMessages.createQueryBuilder('message')
diff --git a/src/server/api/endpoints/mute/list.ts b/src/server/api/endpoints/mute/list.ts
index 5f2d184472..0fd8a4860d 100644
--- a/src/server/api/endpoints/mute/list.ts
+++ b/src/server/api/endpoints/mute/list.ts
@@ -44,7 +44,7 @@ export default define(meta, async (ps, me) => {
 		.andWhere(`muting.muterId = :meId`, { meId: me.id });
 
 	const mutings = await query
-		.take(ps.limit)
+		.take(ps.limit!)
 		.getMany();
 
 	return await Mutings.packMany(mutings, me);
diff --git a/src/server/api/endpoints/my/apps.ts b/src/server/api/endpoints/my/apps.ts
index d205d1674c..e8b26362a4 100644
--- a/src/server/api/endpoints/my/apps.ts
+++ b/src/server/api/endpoints/my/apps.ts
@@ -32,7 +32,7 @@ export default define(meta, async (ps, user) => {
 
 	const apps = await Apps.find({
 		where: query,
-		take: ps.limit,
+		take: ps.limit!,
 		skip: ps.offset,
 	});
 
diff --git a/src/server/api/endpoints/notes.ts b/src/server/api/endpoints/notes.ts
index 10f6e39845..17ba969350 100644
--- a/src/server/api/endpoints/notes.ts
+++ b/src/server/api/endpoints/notes.ts
@@ -100,7 +100,7 @@ export default define(meta, async (ps) => {
 	//	query.isBot = bot;
 	//}
 
-	const notes = await query.take(ps.limit).getMany();
+	const notes = await query.take(ps.limit!).getMany();
 
 	return await Notes.packMany(notes);
 });
diff --git a/src/server/api/endpoints/notes/children.ts b/src/server/api/endpoints/notes/children.ts
index 72f2c39d6a..2b4ae2a312 100644
--- a/src/server/api/endpoints/notes/children.ts
+++ b/src/server/api/endpoints/notes/children.ts
@@ -66,7 +66,7 @@ export default define(meta, async (ps, user) => {
 	if (user) generateVisibilityQuery(query, user);
 	if (user) generateMuteQuery(query, user);
 
-	const notes = await query.take(ps.limit).getMany();
+	const notes = await query.take(ps.limit!).getMany();
 
 	return await Notes.packMany(notes, user);
 });
diff --git a/src/server/api/endpoints/notes/conversation.ts b/src/server/api/endpoints/notes/conversation.ts
index 6defd79042..6b26e31c07 100644
--- a/src/server/api/endpoints/notes/conversation.ts
+++ b/src/server/api/endpoints/notes/conversation.ts
@@ -64,12 +64,13 @@ export default define(meta, async (ps, user) => {
 	async function get(id: any) {
 		i++;
 		const p = await Notes.findOne(id);
+		if (p == null) return;
 
-		if (i > ps.offset) {
+		if (i > ps.offset!) {
 			conversation.push(p);
 		}
 
-		if (conversation.length == ps.limit) {
+		if (conversation.length == ps.limit!) {
 			return;
 		}
 
diff --git a/src/server/api/endpoints/notes/create.ts b/src/server/api/endpoints/notes/create.ts
index 138f05fb3b..83649015d8 100644
--- a/src/server/api/endpoints/notes/create.ts
+++ b/src/server/api/endpoints/notes/create.ts
@@ -225,23 +225,24 @@ export const meta = {
 export default define(meta, async (ps, user, app) => {
 	let visibleUsers: User[] = [];
 	if (ps.visibleUserIds) {
-		visibleUsers = await Promise.all(ps.visibleUserIds.map(id => Users.findOne(id)));
+		visibleUsers = (await Promise.all(ps.visibleUserIds.map(id => Users.findOne(id))))
+			.filter(x => x != null) as User[];
 	}
 
 	let files: DriveFile[] = [];
 	const fileIds = ps.fileIds != null ? ps.fileIds : ps.mediaIds != null ? ps.mediaIds : null;
 	if (fileIds != null) {
-		files = await Promise.all(fileIds.map(fileId => {
-			return DriveFiles.findOne({
+		files = (await Promise.all(fileIds.map(fileId =>
+			DriveFiles.findOne({
 				id: fileId,
 				userId: user.id
-			});
-		}));
+			})
+		))).filter(file => file != null) as DriveFile[];
 
-		files = files.filter(file => file != null);
+		files = files;
 	}
 
-	let renote: Note = null;
+	let renote: Note | undefined;
 	if (ps.renoteId != null) {
 		// Fetch renote to note
 		renote = await Notes.findOne(ps.renoteId);
@@ -253,7 +254,7 @@ export default define(meta, async (ps, user, app) => {
 		}
 	}
 
-	let reply: Note = null;
+	let reply: Note | undefined;
 	if (ps.replyId != null) {
 		// Fetch reply
 		reply = await Notes.findOne(ps.replyId);
@@ -290,8 +291,8 @@ export default define(meta, async (ps, user, app) => {
 			choices: ps.poll.choices,
 			multiple: ps.poll.multiple || false,
 			expiresAt: ps.poll.expiresAt ? new Date(ps.poll.expiresAt) : null
-		} : null,
-		text: ps.text,
+		} : undefined,
+		text: ps.text || undefined,
 		reply,
 		renote,
 		cw: ps.cw,
@@ -300,9 +301,9 @@ export default define(meta, async (ps, user, app) => {
 		localOnly: ps.localOnly,
 		visibility: ps.visibility,
 		visibleUsers,
-		apMentions: ps.noExtractMentions ? [] : null,
-		apHashtags: ps.noExtractHashtags ? [] : null,
-		apEmojis: ps.noExtractEmojis ? [] : null,
+		apMentions: ps.noExtractMentions ? [] : undefined,
+		apHashtags: ps.noExtractHashtags ? [] : undefined,
+		apEmojis: ps.noExtractEmojis ? [] : undefined,
 		geo: ps.geo
 	});
 
diff --git a/src/server/api/endpoints/notes/delete.ts b/src/server/api/endpoints/notes/delete.ts
index dbaf91bca3..17d44c424d 100644
--- a/src/server/api/endpoints/notes/delete.ts
+++ b/src/server/api/endpoints/notes/delete.ts
@@ -6,6 +6,7 @@ import * as ms from 'ms';
 import { getNote } from '../../common/getters';
 import { ApiError } from '../../error';
 import { Users } from '../../../../models';
+import { ensure } from '../../../../prelude/ensure';
 
 export const meta = {
 	stability: 'stable',
@@ -63,5 +64,5 @@ export default define(meta, async (ps, user) => {
 	}
 
 	// この操作を行うのが投稿者とは限らない(例えばモデレーター)ため
-	await deleteNote(await Users.findOne(note.userId), note);
+	await deleteNote(await Users.findOne(note.userId).then(ensure), note);
 });
diff --git a/src/server/api/endpoints/notes/featured.ts b/src/server/api/endpoints/notes/featured.ts
index c44a5275bb..5d2e5b7d44 100644
--- a/src/server/api/endpoints/notes/featured.ts
+++ b/src/server/api/endpoints/notes/featured.ts
@@ -41,7 +41,7 @@ export default define(meta, async (ps, user) => {
 
 	if (user) generateMuteQuery(query, user);
 
-	const notes = await query.orderBy('note.score', 'DESC').take(ps.limit).getMany();
+	const notes = await query.orderBy('note.score', 'DESC').take(ps.limit!).getMany();
 
 	return await Notes.packMany(notes, user);
 });
diff --git a/src/server/api/endpoints/notes/global-timeline.ts b/src/server/api/endpoints/notes/global-timeline.ts
index 7bf62f366b..ceffb1cf4a 100644
--- a/src/server/api/endpoints/notes/global-timeline.ts
+++ b/src/server/api/endpoints/notes/global-timeline.ts
@@ -84,7 +84,7 @@ export default define(meta, async (ps, user) => {
 	}
 	//#endregion
 
-	const timeline = await query.take(ps.limit).getMany();
+	const timeline = await query.take(ps.limit!).getMany();
 
 	if (user) {
 		activeUsersChart.update(user);
diff --git a/src/server/api/endpoints/notes/hybrid-timeline.ts b/src/server/api/endpoints/notes/hybrid-timeline.ts
index 76f1682a95..6dfb143003 100644
--- a/src/server/api/endpoints/notes/hybrid-timeline.ts
+++ b/src/server/api/endpoints/notes/hybrid-timeline.ts
@@ -185,7 +185,7 @@ export default define(meta, async (ps, user) => {
 	}
 	//#endregion
 
-	const timeline = await query.take(ps.limit).getMany();
+	const timeline = await query.take(ps.limit!).getMany();
 
 	if (user) {
 		activeUsersChart.update(user);
diff --git a/src/server/api/endpoints/notes/local-timeline.ts b/src/server/api/endpoints/notes/local-timeline.ts
index cd07341342..c10c0d7482 100644
--- a/src/server/api/endpoints/notes/local-timeline.ts
+++ b/src/server/api/endpoints/notes/local-timeline.ts
@@ -100,11 +100,11 @@ export default define(meta, async (ps, user) => {
 		query.andWhere('note.fileIds != \'{}\'');
 	}
 
-	if (ps.fileType) {
+	if (ps.fileType != null) {
 		query.andWhere('note.fileIds != \'{}\'');
 		query.andWhere(new Brackets(qb => {
-			for (const type of ps.fileType) {
-				const i = ps.fileType.indexOf(type);
+			for (const type of ps.fileType!) {
+				const i = ps.fileType!.indexOf(type);
 				qb.orWhere(`:type${i} = ANY(note.attachedFileTypes)`, { [`type${i}`]: type });
 			}
 		}));
@@ -120,7 +120,7 @@ export default define(meta, async (ps, user) => {
 	}
 	//#endregion
 
-	const timeline = await query.take(ps.limit).getMany();
+	const timeline = await query.take(ps.limit!).getMany();
 
 	if (user) {
 		activeUsersChart.update(user);
diff --git a/src/server/api/endpoints/notes/mentions.ts b/src/server/api/endpoints/notes/mentions.ts
index 0bbe7d3327..b7f614915b 100644
--- a/src/server/api/endpoints/notes/mentions.ts
+++ b/src/server/api/endpoints/notes/mentions.ts
@@ -74,7 +74,7 @@ export default define(meta, async (ps, user) => {
 		query.setParameters(followingQuery.getParameters());
 	}
 
-	const mentions = await query.take(ps.limit).getMany();
+	const mentions = await query.take(ps.limit!).getMany();
 
 	for (const note of mentions) {
 		read(user.id, note.id);
diff --git a/src/server/api/endpoints/notes/polls/recommendation.ts b/src/server/api/endpoints/notes/polls/recommendation.ts
index ff838d4f4f..cbd4d35cd4 100644
--- a/src/server/api/endpoints/notes/polls/recommendation.ts
+++ b/src/server/api/endpoints/notes/polls/recommendation.ts
@@ -58,7 +58,7 @@ export default define(meta, async (ps, user) => {
 	query.setParameters(mutingQuery.getParameters());
 	//#endregion
 
-	const polls = await query.take(ps.limit).skip(ps.offset).getMany();
+	const polls = await query.take(ps.limit!).skip(ps.offset).getMany();
 
 	if (polls.length === 0) return [];
 
diff --git a/src/server/api/endpoints/notes/polls/vote.ts b/src/server/api/endpoints/notes/polls/vote.ts
index dd4d93c7ac..68dee66828 100644
--- a/src/server/api/endpoints/notes/polls/vote.ts
+++ b/src/server/api/endpoints/notes/polls/vote.ts
@@ -14,6 +14,7 @@ import { PollVotes, NoteWatchings, Users, Polls, UserProfiles } from '../../../.
 import { Not } from 'typeorm';
 import { IRemoteUser } from '../../../../../models/entities/user';
 import { genId } from '../../../../../misc/gen-id';
+import { ensure } from '../../../../../prelude/ensure';
 
 export const meta = {
 	desc: {
@@ -87,7 +88,7 @@ export default define(meta, async (ps, user) => {
 		throw new ApiError(meta.errors.noPoll);
 	}
 
-	const poll = await Polls.findOne({ noteId: note.id });
+	const poll = await Polls.findOne({ noteId: note.id }).then(ensure);
 
 	if (poll.expiresAt && poll.expiresAt < createdAt) {
 		throw new ApiError(meta.errors.alreadyExpired);
@@ -149,7 +150,7 @@ export default define(meta, async (ps, user) => {
 		}
 	});
 
-	const profile = await UserProfiles.findOne({ userId: user.id });
+	const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure);
 
 	// この投稿をWatchする
 	if (profile.autoWatch !== false) {
@@ -158,7 +159,7 @@ export default define(meta, async (ps, user) => {
 
 	// リモート投票の場合リプライ送信
 	if (note.userHost != null) {
-		const pollOwner: IRemoteUser = await Users.findOne(note.userId);
+		const pollOwner = await Users.findOne(note.userId).then(ensure) as IRemoteUser;
 
 		deliver(user, renderActivity(await renderVote(user, vote, note, poll, pollOwner)), pollOwner.inbox);
 	}
diff --git a/src/server/api/endpoints/notes/reactions.ts b/src/server/api/endpoints/notes/reactions.ts
index b1b5ca9d33..bcb0b6d1ec 100644
--- a/src/server/api/endpoints/notes/reactions.ts
+++ b/src/server/api/endpoints/notes/reactions.ts
@@ -71,7 +71,7 @@ export default define(meta, async (ps, user) => {
 
 	const reactions = await NoteReactions.find({
 		where: query,
-		take: ps.limit,
+		take: ps.limit!,
 		skip: ps.offset,
 		order: {
 			id: -1
diff --git a/src/server/api/endpoints/notes/renotes.ts b/src/server/api/endpoints/notes/renotes.ts
index 81b899836d..74a8ea918e 100644
--- a/src/server/api/endpoints/notes/renotes.ts
+++ b/src/server/api/endpoints/notes/renotes.ts
@@ -70,7 +70,7 @@ export default define(meta, async (ps, user) => {
 	if (user) generateVisibilityQuery(query, user);
 	if (user) generateMuteQuery(query, user);
 
-	const renotes = await query.take(ps.limit).getMany();
+	const renotes = await query.take(ps.limit!).getMany();
 
 	return await Notes.packMany(renotes, user);
 });
diff --git a/src/server/api/endpoints/notes/replies.ts b/src/server/api/endpoints/notes/replies.ts
index 09b0f17164..980ff2446e 100644
--- a/src/server/api/endpoints/notes/replies.ts
+++ b/src/server/api/endpoints/notes/replies.ts
@@ -61,7 +61,7 @@ export default define(meta, async (ps, user) => {
 	if (user) generateVisibilityQuery(query, user);
 	if (user) generateMuteQuery(query, user);
 
-	const timeline = await query.take(ps.limit).getMany();
+	const timeline = await query.take(ps.limit!).getMany();
 
 	return await Notes.packMany(timeline, user);
 });
diff --git a/src/server/api/endpoints/notes/search-by-tag.ts b/src/server/api/endpoints/notes/search-by-tag.ts
index 48de88d36e..cba3724b6f 100644
--- a/src/server/api/endpoints/notes/search-by-tag.ts
+++ b/src/server/api/endpoints/notes/search-by-tag.ts
@@ -100,7 +100,7 @@ export default define(meta, async (ps, me) => {
 	} else {
 		let i = 0;
 		query.andWhere(new Brackets(qb => {
-			for (const tags of ps.query) {
+			for (const tags of ps.query!) {
 				qb.orWhere(new Brackets(qb => {
 					for (const tag of tags) {
 						qb.andWhere(`:tag${i} = ANY(note.tags)`, { [`tag${i}`]: tag });
@@ -140,7 +140,7 @@ export default define(meta, async (ps, me) => {
 	}
 
 	// Search notes
-	const notes = await query.take(ps.limit).getMany();
+	const notes = await query.take(ps.limit!).getMany();
 
 	return await Notes.packMany(notes, me);
 });
diff --git a/src/server/api/endpoints/notes/search.ts b/src/server/api/endpoints/notes/search.ts
index cc88fb9380..4d5ac6fbe0 100644
--- a/src/server/api/endpoints/notes/search.ts
+++ b/src/server/api/endpoints/notes/search.ts
@@ -54,7 +54,7 @@ export default define(meta, async (ps, me) => {
 		index: 'misskey',
 		type: 'note',
 		body: {
-			size: ps.limit,
+			size: ps.limit!,
 			from: ps.offset,
 			query: {
 				simple_query_string: {
diff --git a/src/server/api/endpoints/notes/timeline.ts b/src/server/api/endpoints/notes/timeline.ts
index e22db4d1b0..c27f3df1b7 100644
--- a/src/server/api/endpoints/notes/timeline.ts
+++ b/src/server/api/endpoints/notes/timeline.ts
@@ -171,7 +171,7 @@ export default define(meta, async (ps, user) => {
 	}
 	//#endregion
 
-	const timeline = await query.take(ps.limit).getMany();
+	const timeline = await query.take(ps.limit!).getMany();
 
 	activeUsersChart.update(user);
 
diff --git a/src/server/api/endpoints/notes/user-list-timeline.ts b/src/server/api/endpoints/notes/user-list-timeline.ts
index deda04acb4..05f171af8b 100644
--- a/src/server/api/endpoints/notes/user-list-timeline.ts
+++ b/src/server/api/endpoints/notes/user-list-timeline.ts
@@ -189,7 +189,7 @@ export default define(meta, async (ps, user) => {
 	}
 	//#endregion
 
-	const timeline = await query.take(ps.limit).getMany();
+	const timeline = await query.take(ps.limit!).getMany();
 
 	activeUsersChart.update(user);
 
diff --git a/src/server/api/endpoints/users.ts b/src/server/api/endpoints/users.ts
index f99165f3d5..18af0a2685 100644
--- a/src/server/api/endpoints/users.ts
+++ b/src/server/api/endpoints/users.ts
@@ -88,7 +88,7 @@ export default define(meta, async (ps, me) => {
 
 	if (me) generateMuteQueryForUsers(query, me);
 
-	query.take(ps.limit);
+	query.take(ps.limit!);
 	query.skip(ps.offset);
 
 	const users = await query.getMany();
diff --git a/src/server/api/endpoints/users/followers.ts b/src/server/api/endpoints/users/followers.ts
index 64d63e2d03..88a474be7c 100644
--- a/src/server/api/endpoints/users/followers.ts
+++ b/src/server/api/endpoints/users/followers.ts
@@ -66,7 +66,7 @@ export const meta = {
 export default define(meta, async (ps, me) => {
 	const user = await Users.findOne(ps.userId != null
 		? { id: ps.userId }
-		: { usernameLower: ps.username.toLowerCase(), host: toPuny(ps.host) });
+		: { usernameLower: ps.username!.toLowerCase(), host: toPuny(ps.host!) });
 
 	if (user == null) {
 		throw new ApiError(meta.errors.noSuchUser);
@@ -76,7 +76,7 @@ export default define(meta, async (ps, me) => {
 		.andWhere(`following.followeeId = :userId`, { userId: user.id });
 
 	const followings = await query
-		.take(ps.limit)
+		.take(ps.limit!)
 		.getMany();
 
 	return await Followings.packMany(followings, me, { populateFollower: true });
diff --git a/src/server/api/endpoints/users/following.ts b/src/server/api/endpoints/users/following.ts
index 0e28001680..5e017150e8 100644
--- a/src/server/api/endpoints/users/following.ts
+++ b/src/server/api/endpoints/users/following.ts
@@ -66,7 +66,7 @@ export const meta = {
 export default define(meta, async (ps, me) => {
 	const user = await Users.findOne(ps.userId != null
 		? { id: ps.userId }
-		: { usernameLower: ps.username.toLowerCase(), host: toPuny(ps.host) });
+		: { usernameLower: ps.username!.toLowerCase(), host: toPuny(ps.host!) });
 
 	if (user == null) {
 		throw new ApiError(meta.errors.noSuchUser);
@@ -76,7 +76,7 @@ export default define(meta, async (ps, me) => {
 		.andWhere(`following.followerId = :userId`, { userId: user.id });
 
 	const followings = await query
-		.take(ps.limit)
+		.take(ps.limit!)
 		.getMany();
 
 	return await Followings.packMany(followings, me, { populateFollowee: true });
diff --git a/src/server/api/endpoints/users/get-frequently-replied-users.ts b/src/server/api/endpoints/users/get-frequently-replied-users.ts
index f82f437629..a1d140c6c9 100644
--- a/src/server/api/endpoints/users/get-frequently-replied-users.ts
+++ b/src/server/api/endpoints/users/get-frequently-replied-users.ts
@@ -94,7 +94,7 @@ export default define(meta, async (ps, me) => {
 	const repliedUsersSorted = Object.keys(repliedUsers).sort((a, b) => repliedUsers[b] - repliedUsers[a]);
 
 	// Extract top replied users
-	const topRepliedUsers = repliedUsersSorted.slice(0, ps.limit);
+	const topRepliedUsers = repliedUsersSorted.slice(0, ps.limit!);
 
 	// Make replies object (includes weights)
 	const repliesObj = await Promise.all(topRepliedUsers.map(async (user) => ({
diff --git a/src/server/api/endpoints/users/notes.ts b/src/server/api/endpoints/users/notes.ts
index 6df394cbb1..da23be3c55 100644
--- a/src/server/api/endpoints/users/notes.ts
+++ b/src/server/api/endpoints/users/notes.ts
@@ -153,11 +153,11 @@ export default define(meta, async (ps, me) => {
 		query.andWhere('note.fileIds != \'{}\'');
 	}
 
-	if (ps.fileType) {
+	if (ps.fileType != null) {
 		query.andWhere('note.fileIds != \'{}\'');
 		query.andWhere(new Brackets(qb => {
-			for (const type of ps.fileType) {
-				const i = ps.fileType.indexOf(type);
+			for (const type of ps.fileType!) {
+				const i = ps.fileType!.indexOf(type);
 				qb.orWhere(`:type${i} = ANY(note.attachedFileTypes)`, { [`type${i}`]: type });
 			}
 		}));
@@ -194,7 +194,7 @@ export default define(meta, async (ps, me) => {
 
 	//#endregion
 
-	const timeline = await query.take(ps.limit).getMany();
+	const timeline = await query.take(ps.limit!).getMany();
 
 	return await Notes.packMany(timeline, user);
 });
diff --git a/src/server/api/endpoints/users/recommendation.ts b/src/server/api/endpoints/users/recommendation.ts
index 2c82d6613e..9e16e34e39 100644
--- a/src/server/api/endpoints/users/recommendation.ts
+++ b/src/server/api/endpoints/users/recommendation.ts
@@ -53,7 +53,7 @@ export default define(meta, async (ps, me) => {
 
 	query.setParameters(followingQuery.getParameters());
 
-	const users = await query.take(ps.limit).skip(ps.offset).getMany();
+	const users = await query.take(ps.limit!).skip(ps.offset).getMany();
 
 	return await Users.packMany(users, me, { detail: true });
 });
diff --git a/src/server/api/endpoints/users/search.ts b/src/server/api/endpoints/users/search.ts
index 443bd507f3..96da221d97 100644
--- a/src/server/api/endpoints/users/search.ts
+++ b/src/server/api/endpoints/users/search.ts
@@ -71,16 +71,16 @@ export default define(meta, async (ps, me) => {
 			.where('user.host IS NULL')
 			.andWhere('user.isSuspended = FALSE')
 			.andWhere('user.usernameLower like :username', { username: ps.query.replace('@', '').toLowerCase() + '%' })
-			.take(ps.limit)
+			.take(ps.limit!)
 			.skip(ps.offset)
 			.getMany();
 
-		if (users.length < ps.limit && !ps.localOnly) {
+		if (users.length < ps.limit! && !ps.localOnly) {
 			const otherUsers = await Users.createQueryBuilder('user')
 				.where('user.host IS NOT NULL')
 				.andWhere('user.isSuspended = FALSE')
 				.andWhere('user.usernameLower like :username', { username: ps.query.replace('@', '').toLowerCase() + '%' })
-				.take(ps.limit - users.length)
+				.take(ps.limit! - users.length)
 				.getMany();
 
 			users = users.concat(otherUsers);
diff --git a/src/server/api/endpoints/users/show.ts b/src/server/api/endpoints/users/show.ts
index ae93e40eaa..2be193f89b 100644
--- a/src/server/api/endpoints/users/show.ts
+++ b/src/server/api/endpoints/users/show.ts
@@ -74,7 +74,7 @@ export default define(meta, async (ps, me) => {
 		})));
 	} else {
 		// Lookup user
-		if (typeof ps.host === 'string') {
+		if (typeof ps.host === 'string' && typeof ps.username === 'string') {
 			user = await resolveUser(ps.username, ps.host).catch(e => {
 				apiLogger.warn(`failed to resolve remote user: ${e}`);
 				throw new ApiError(meta.errors.failedToResolveRemoteUser);
@@ -82,7 +82,7 @@ export default define(meta, async (ps, me) => {
 		} else {
 			const q: any = ps.userId != null
 				? { id: ps.userId }
-				: { usernameLower: ps.username.toLowerCase(), host: null };
+				: { usernameLower: ps.username!.toLowerCase(), host: null };
 
 			user = await Users.findOne(q);
 		}
@@ -94,7 +94,7 @@ export default define(meta, async (ps, me) => {
 		// ユーザー情報更新
 		if (Users.isRemoteUser(user)) {
 			if (user.lastFetchedAt == null || Date.now() - user.lastFetchedAt.getTime() > 1000 * 60 * 60 * 24) {
-				resolveUser(ps.username, ps.host, { }, true);
+				resolveUser(user.username, user.host, { }, true);
 			}
 		}
 
diff --git a/src/server/api/error.ts b/src/server/api/error.ts
index ca441d5811..cb0bdc9f47 100644
--- a/src/server/api/error.ts
+++ b/src/server/api/error.ts
@@ -1,3 +1,5 @@
+type E = { message: string, code: string, id: string, kind?: 'client' | 'server', httpStatusCode?: number };
+
 export class ApiError extends Error {
 	public message: string;
 	public code: string;
@@ -6,7 +8,7 @@ export class ApiError extends Error {
 	public httpStatusCode?: number;
 	public info?: any;
 
-	constructor(e?: { message: string, code: string, id: string, kind?: 'client' | 'server', httpStatusCode?: number }, info?: any) {
+	constructor(e?: E | null | undefined, info?: any | null | undefined) {
 		if (e == null) e = {
 			message: 'Internal error occurred. Please contact us if the error persists.',
 			code: 'INTERNAL_ERROR',
diff --git a/src/server/api/limiter.ts b/src/server/api/limiter.ts
index e29c061337..8a6c94458e 100644
--- a/src/server/api/limiter.ts
+++ b/src/server/api/limiter.ts
@@ -14,7 +14,7 @@ export default (endpoint: IEndpoint, user: User) => new Promise((ok, reject) =>
 		return;
 	}
 
-	const limitation = endpoint.meta.limit;
+	const limitation = endpoint.meta.limit!;
 
 	const key = limitation.hasOwnProperty('key')
 		? limitation.key
@@ -41,7 +41,7 @@ export default (endpoint: IEndpoint, user: User) => new Promise((ok, reject) =>
 			id: `${user.id}:${key}:min`,
 			duration: limitation.minInterval,
 			max: 1,
-			db: limiterDB
+			db: limiterDB!
 		});
 
 		minIntervalLimiter.get((err, info) => {
@@ -69,7 +69,7 @@ export default (endpoint: IEndpoint, user: User) => new Promise((ok, reject) =>
 			id: `${user.id}:${key}`,
 			duration: limitation.duration,
 			max: limitation.max,
-			db: limiterDB
+			db: limiterDB!
 		});
 
 		limiter.get((err, info) => {
diff --git a/src/server/api/private/signin.ts b/src/server/api/private/signin.ts
index fe2e5577c2..676546f2aa 100644
--- a/src/server/api/private/signin.ts
+++ b/src/server/api/private/signin.ts
@@ -7,6 +7,7 @@ import config from '../../../config';
 import { Users, Signins, UserProfiles } from '../../../models';
 import { ILocalUser } from '../../../models/entities/user';
 import { genId } from '../../../misc/gen-id';
+import { ensure } from '../../../prelude/ensure';
 
 export default async (ctx: Koa.BaseContext) => {
 	ctx.set('Access-Control-Allow-Origin', config.url);
@@ -45,10 +46,10 @@ export default async (ctx: Koa.BaseContext) => {
 		return;
 	}
 
-	const profile = await UserProfiles.findOne({ userId: user.id });
+	const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure);
 
 	// Compare password
-	const same = await bcrypt.compare(password, profile.password);
+	const same = await bcrypt.compare(password, profile.password!);
 
 	if (same) {
 		if (profile.twoFactorEnabled) {
diff --git a/src/server/api/private/signup.ts b/src/server/api/private/signup.ts
index 03d83efd94..ea4df060f8 100644
--- a/src/server/api/private/signup.ts
+++ b/src/server/api/private/signup.ts
@@ -21,7 +21,7 @@ export default async (ctx: Koa.BaseContext) => {
 
 	// Verify recaptcha
 	// ただしテスト時はこの機構は障害となるため無効にする
-	if (process.env.NODE_ENV !== 'test' && instance.enableRecaptcha) {
+	if (process.env.NODE_ENV !== 'test' && instance.enableRecaptcha && instance.recaptchaSecretKey) {
 		recaptcha.init({
 			secret_key: instance.recaptchaSecretKey
 		});
@@ -100,7 +100,7 @@ export default async (ctx: Koa.BaseContext) => {
 			e ? j(e) : s([publicKey, privateKey])
 		));
 
-	let account: User;
+	let account!: User;
 
 	// Start transaction
 	await getConnection().transaction(async transactionalEntityManager => {
diff --git a/src/server/api/service/discord.ts b/src/server/api/service/discord.ts
index 879b8b4849..b2561dee61 100644
--- a/src/server/api/service/discord.ts
+++ b/src/server/api/service/discord.ts
@@ -10,6 +10,7 @@ import signin from '../common/signin';
 import fetchMeta from '../../../misc/fetch-meta';
 import { Users, UserProfiles } from '../../../models';
 import { ILocalUser } from '../../../models/entities/user';
+import { ensure } from '../../../prelude/ensure';
 
 function getUserToken(ctx: Koa.BaseContext) {
 	return ((ctx.headers['cookie'] || '').match(/i=(!\w+)/) || [null, null])[1];
@@ -43,7 +44,7 @@ router.get('/disconnect/discord', async ctx => {
 	const user = await Users.findOne({
 		host: null,
 		token: userToken
-	});
+	}).then(ensure);
 
 	await UserProfiles.update({
 		userId: user.id
@@ -71,8 +72,8 @@ async function getOAuth2() {
 
 	if (meta.enableDiscordIntegration) {
 		return new OAuth2(
-			meta.discordClientId,
-			meta.discordClientSecret,
+			meta.discordClientId!,
+			meta.discordClientSecret!,
 			'https://discordapp.com/',
 			'api/oauth2/authorize',
 			'api/oauth2/token');
@@ -82,6 +83,8 @@ async function getOAuth2() {
 }
 
 router.get('/connect/discord', async ctx => {
+	if (redis == null) return;
+
 	if (!compareOrigin(ctx)) {
 		ctx.throw(400, 'invalid origin');
 		return;
@@ -103,10 +106,12 @@ router.get('/connect/discord', async ctx => {
 	redis.set(userToken, JSON.stringify(params));
 
 	const oauth2 = await getOAuth2();
-	ctx.redirect(oauth2.getAuthorizeUrl(params));
+	ctx.redirect(oauth2!.getAuthorizeUrl(params));
 });
 
 router.get('/signin/discord', async ctx => {
+	if (redis == null) return;
+
 	const sessid = uuid();
 
 	const params = {
@@ -129,10 +134,12 @@ router.get('/signin/discord', async ctx => {
 	redis.set(sessid, JSON.stringify(params));
 
 	const oauth2 = await getOAuth2();
-	ctx.redirect(oauth2.getAuthorizeUrl(params));
+	ctx.redirect(oauth2!.getAuthorizeUrl(params));
 });
 
 router.get('/dc/cb', async ctx => {
+	if (redis == null) return;
+
 	const userToken = getUserToken(ctx);
 
 	const oauth2 = await getOAuth2();
@@ -153,7 +160,7 @@ router.get('/dc/cb', async ctx => {
 		}
 
 		const { redirect_uri, state } = await new Promise<any>((res, rej) => {
-			redis.get(sessid, async (_, state) => {
+			redis!.get(sessid, async (_, state) => {
 				res(JSON.parse(state));
 			});
 		});
@@ -164,24 +171,22 @@ router.get('/dc/cb', async ctx => {
 		}
 
 		const { accessToken, refreshToken, expiresDate } = await new Promise<any>((res, rej) =>
-			oauth2.getOAuthAccessToken(
-				code,
-				{
-					grant_type: 'authorization_code',
-					redirect_uri
-				},
-				(err, accessToken, refreshToken, result) => {
-					if (err)
-						rej(err);
-					else if (result.error)
-						rej(result.error);
-					else
+			oauth2!.getOAuthAccessToken(code, {
+				grant_type: 'authorization_code',
+				redirect_uri
+			}, (err, accessToken, refreshToken, result) => {
+				if (err) {
+					rej(err);
+				} else if (result.error) {
+					rej(result.error);
+				} else {
 					res({
 						accessToken,
 						refreshToken,
 						expiresDate: Date.now() + Number(result.expires_in) * 1000
 					});
-				}));
+				}
+			}));
 
 		const { id, username, discriminator } = await new Promise<any>((res, rej) =>
 			request({
@@ -191,10 +196,11 @@ router.get('/dc/cb', async ctx => {
 					'User-Agent': config.userAgent
 				}
 			}, (err, response, body) => {
-				if (err)
+				if (err) {
 					rej(err);
-				else
+				} else {
 					res(JSON.parse(body));
+				}
 			}));
 
 		if (!id || !username || !discriminator) {
@@ -235,7 +241,7 @@ router.get('/dc/cb', async ctx => {
 		}
 
 		const { redirect_uri, state } = await new Promise<any>((res, rej) => {
-			redis.get(userToken, async (_, state) => {
+			redis!.get(userToken, async (_, state) => {
 				res(JSON.parse(state));
 			});
 		});
@@ -246,24 +252,22 @@ router.get('/dc/cb', async ctx => {
 		}
 
 		const { accessToken, refreshToken, expiresDate } = await new Promise<any>((res, rej) =>
-			oauth2.getOAuthAccessToken(
-				code,
-				{
-					grant_type: 'authorization_code',
-					redirect_uri
-				},
-				(err, accessToken, refreshToken, result) => {
-					if (err)
-						rej(err);
-					else if (result.error)
-						rej(result.error);
-					else
-						res({
-							accessToken,
-							refreshToken,
-							expiresDate: Date.now() + Number(result.expires_in) * 1000
-						});
-				}));
+			oauth2!.getOAuthAccessToken(code, {
+				grant_type: 'authorization_code',
+				redirect_uri
+			}, (err, accessToken, refreshToken, result) => {
+				if (err) {
+					rej(err);
+				} else if (result.error) {
+					rej(result.error);
+				} else {
+					res({
+						accessToken,
+						refreshToken,
+						expiresDate: Date.now() + Number(result.expires_in) * 1000
+					});
+				}
+			}));
 
 		const { id, username, discriminator } = await new Promise<any>((res, rej) =>
 			request({
@@ -273,10 +277,11 @@ router.get('/dc/cb', async ctx => {
 					'User-Agent': config.userAgent
 				}
 			}, (err, response, body) => {
-				if (err)
+				if (err) {
 					rej(err);
-				else
+				} else {
 					res(JSON.parse(body));
+				}
 			}));
 
 		if (!id || !username || !discriminator) {
@@ -287,7 +292,7 @@ router.get('/dc/cb', async ctx => {
 		const user = await Users.findOne({
 			host: null,
 			token: userToken
-		});
+		}).then(ensure);
 
 		await UserProfiles.update({ userId: user.id }, {
 			discord: true,
diff --git a/src/server/api/service/github.ts b/src/server/api/service/github.ts
index 580947811b..4878d8c529 100644
--- a/src/server/api/service/github.ts
+++ b/src/server/api/service/github.ts
@@ -10,6 +10,7 @@ import signin from '../common/signin';
 import fetchMeta from '../../../misc/fetch-meta';
 import { Users, UserProfiles } from '../../../models';
 import { ILocalUser } from '../../../models/entities/user';
+import { ensure } from '../../../prelude/ensure';
 
 function getUserToken(ctx: Koa.BaseContext) {
 	return ((ctx.headers['cookie'] || '').match(/i=(!\w+)/) || [null, null])[1];
@@ -43,7 +44,7 @@ router.get('/disconnect/github', async ctx => {
 	const user = await Users.findOne({
 		host: null,
 		token: userToken
-	});
+	}).then(ensure);
 
 	await UserProfiles.update({
 		userId: user.id
@@ -66,7 +67,7 @@ router.get('/disconnect/github', async ctx => {
 async function getOath2() {
 	const meta = await fetchMeta();
 
-	if (meta.enableGithubIntegration) {
+	if (meta.enableGithubIntegration && meta.githubClientId && meta.githubClientSecret) {
 		return new OAuth2(
 			meta.githubClientId,
 			meta.githubClientSecret,
@@ -79,6 +80,8 @@ async function getOath2() {
 }
 
 router.get('/connect/github', async ctx => {
+	if (redis == null) return;
+
 	if (!compareOrigin(ctx)) {
 		ctx.throw(400, 'invalid origin');
 		return;
@@ -99,10 +102,12 @@ router.get('/connect/github', async ctx => {
 	redis.set(userToken, JSON.stringify(params));
 
 	const oauth2 = await getOath2();
-	ctx.redirect(oauth2.getAuthorizeUrl(params));
+	ctx.redirect(oauth2!.getAuthorizeUrl(params));
 });
 
 router.get('/signin/github', async ctx => {
+	if (redis == null) return;
+
 	const sessid = uuid();
 
 	const params = {
@@ -124,10 +129,12 @@ router.get('/signin/github', async ctx => {
 	redis.set(sessid, JSON.stringify(params));
 
 	const oauth2 = await getOath2();
-	ctx.redirect(oauth2.getAuthorizeUrl(params));
+	ctx.redirect(oauth2!.getAuthorizeUrl(params));
 });
 
 router.get('/gh/cb', async ctx => {
+	if (redis == null) return;
+
 	const userToken = getUserToken(ctx);
 
 	const oauth2 = await getOath2();
@@ -148,7 +155,7 @@ router.get('/gh/cb', async ctx => {
 		}
 
 		const { redirect_uri, state } = await new Promise<any>((res, rej) => {
-			redis.get(sessid, async (_, state) => {
+			redis!.get(sessid, async (_, state) => {
 				res(JSON.parse(state));
 			});
 		});
@@ -159,17 +166,17 @@ router.get('/gh/cb', async ctx => {
 		}
 
 		const { accessToken } = await new Promise<any>((res, rej) =>
-			oauth2.getOAuthAccessToken(
-				code,
-				{ redirect_uri },
-				(err, accessToken, refresh, result) => {
-					if (err)
-						rej(err);
-					else if (result.error)
-						rej(result.error);
-					else
-						res({ accessToken });
-				}));
+			oauth2!.getOAuthAccessToken(code, {
+				redirect_uri
+			}, (err, accessToken, refresh, result) => {
+				if (err) {
+					rej(err);
+				} else if (result.error) {
+					rej(result.error);
+				} else {
+					res({ accessToken });
+				}
+			}));
 
 		const { login, id } = await new Promise<any>((res, rej) =>
 			request({
@@ -215,7 +222,7 @@ router.get('/gh/cb', async ctx => {
 		}
 
 		const { redirect_uri, state } = await new Promise<any>((res, rej) => {
-			redis.get(userToken, async (_, state) => {
+			redis!.get(userToken, async (_, state) => {
 				res(JSON.parse(state));
 			});
 		});
@@ -226,7 +233,7 @@ router.get('/gh/cb', async ctx => {
 		}
 
 		const { accessToken } = await new Promise<any>((res, rej) =>
-			oauth2.getOAuthAccessToken(
+			oauth2!.getOAuthAccessToken(
 				code,
 				{ redirect_uri },
 				(err, accessToken, refresh, result) => {
@@ -261,7 +268,7 @@ router.get('/gh/cb', async ctx => {
 		const user = await Users.findOne({
 			host: null,
 			token: userToken
-		});
+		}).then(ensure);
 
 		await UserProfiles.update({ userId: user.id }, {
 			github: true,
diff --git a/src/server/api/service/twitter.ts b/src/server/api/service/twitter.ts
index c0c762c6c3..b35ee8c479 100644
--- a/src/server/api/service/twitter.ts
+++ b/src/server/api/service/twitter.ts
@@ -9,6 +9,7 @@ import signin from '../common/signin';
 import fetchMeta from '../../../misc/fetch-meta';
 import { Users, UserProfiles } from '../../../models';
 import { ILocalUser } from '../../../models/entities/user';
+import { ensure } from '../../../prelude/ensure';
 
 function getUserToken(ctx: Koa.BaseContext) {
 	return ((ctx.headers['cookie'] || '').match(/i=(!\w+)/) || [null, null])[1];
@@ -42,7 +43,7 @@ router.get('/disconnect/twitter', async ctx => {
 	const user = await Users.findOne({
 		host: null,
 		token: userToken
-	});
+	}).then(ensure);
 
 	await UserProfiles.update({
 		userId: user.id
@@ -66,7 +67,7 @@ router.get('/disconnect/twitter', async ctx => {
 async function getTwAuth() {
 	const meta = await fetchMeta();
 
-	if (meta.enableTwitterIntegration) {
+	if (meta.enableTwitterIntegration && meta.twitterConsumerKey && meta.twitterConsumerSecret) {
 		return autwh({
 			consumerKey: meta.twitterConsumerKey,
 			consumerSecret: meta.twitterConsumerSecret,
@@ -78,6 +79,8 @@ async function getTwAuth() {
 }
 
 router.get('/connect/twitter', async ctx => {
+	if (redis == null) return;
+
 	if (!compareOrigin(ctx)) {
 		ctx.throw(400, 'invalid origin');
 		return;
@@ -90,14 +93,16 @@ router.get('/connect/twitter', async ctx => {
 	}
 
 	const twAuth = await getTwAuth();
-	const twCtx = await twAuth.begin();
+	const twCtx = await twAuth!.begin();
 	redis.set(userToken, JSON.stringify(twCtx));
 	ctx.redirect(twCtx.url);
 });
 
 router.get('/signin/twitter', async ctx => {
+	if (redis == null) return;
+
 	const twAuth = await getTwAuth();
-	const twCtx = await twAuth.begin();
+	const twCtx = await twAuth!.begin();
 
 	const sessid = uuid();
 
@@ -117,6 +122,8 @@ router.get('/signin/twitter', async ctx => {
 });
 
 router.get('/tw/cb', async ctx => {
+	if (redis == null) return;
+
 	const userToken = getUserToken(ctx);
 
 	const twAuth = await getTwAuth();
@@ -130,14 +137,14 @@ router.get('/tw/cb', async ctx => {
 		}
 
 		const get = new Promise<any>((res, rej) => {
-			redis.get(sessid, async (_, twCtx) => {
+			redis!.get(sessid, async (_, twCtx) => {
 				res(twCtx);
 			});
 		});
 
 		const twCtx = await get;
 
-		const result = await twAuth.done(JSON.parse(twCtx), ctx.query.oauth_verifier);
+		const result = await twAuth!.done(JSON.parse(twCtx), ctx.query.oauth_verifier);
 
 		const link = await UserProfiles.createQueryBuilder()
 			.where('twitter @> :twitter', {
@@ -163,19 +170,19 @@ router.get('/tw/cb', async ctx => {
 		}
 
 		const get = new Promise<any>((res, rej) => {
-			redis.get(userToken, async (_, twCtx) => {
+			redis!.get(userToken, async (_, twCtx) => {
 				res(twCtx);
 			});
 		});
 
 		const twCtx = await get;
 
-		const result = await twAuth.done(JSON.parse(twCtx), verifier);
+		const result = await twAuth!.done(JSON.parse(twCtx), verifier);
 
 		const user = await Users.findOne({
 			host: null,
 			token: userToken
-		});
+		}).then(ensure);
 
 		await UserProfiles.update({ userId: user.id }, {
 			twitter: true,
diff --git a/src/server/api/stream/channels/admin.ts b/src/server/api/stream/channels/admin.ts
index e2eba10f78..1ff932d1dd 100644
--- a/src/server/api/stream/channels/admin.ts
+++ b/src/server/api/stream/channels/admin.ts
@@ -9,7 +9,7 @@ export default class extends Channel {
 	@autobind
 	public async init(params: any) {
 		// Subscribe admin stream
-		this.subscriber.on(`adminStream:${this.user.id}`, data => {
+		this.subscriber.on(`adminStream:${this.user!.id}`, data => {
 			this.send(data);
 		});
 	}
diff --git a/src/server/api/stream/channels/drive.ts b/src/server/api/stream/channels/drive.ts
index 671aad4366..4112dd9b04 100644
--- a/src/server/api/stream/channels/drive.ts
+++ b/src/server/api/stream/channels/drive.ts
@@ -9,7 +9,7 @@ export default class extends Channel {
 	@autobind
 	public async init(params: any) {
 		// Subscribe drive stream
-		this.subscriber.on(`driveStream:${this.user.id}`, data => {
+		this.subscriber.on(`driveStream:${this.user!.id}`, data => {
 			this.send(data);
 		});
 	}
diff --git a/src/server/api/stream/channels/games/reversi-game.ts b/src/server/api/stream/channels/games/reversi-game.ts
index 158f108c4e..d708eae9f7 100644
--- a/src/server/api/stream/channels/games/reversi-game.ts
+++ b/src/server/api/stream/channels/games/reversi-game.ts
@@ -12,7 +12,7 @@ export default class extends Channel {
 	public static shouldShare = false;
 	public static requireCredential = false;
 
-	private gameId: ReversiGame['id'];
+	private gameId: ReversiGame['id'] | null = null;
 
 	@autobind
 	public async init(params: any) {
@@ -40,7 +40,10 @@ export default class extends Channel {
 
 	@autobind
 	private async updateSettings(key: string, value: any) {
-		const game = await ReversiGames.findOne(this.gameId);
+		if (this.user == null) return;
+
+		const game = await ReversiGames.findOne(this.gameId!);
+		if (game == null) throw 'game not found';
 
 		if (game.isStarted) return;
 		if ((game.user1Id !== this.user.id) && (game.user2Id !== this.user.id)) return;
@@ -49,11 +52,11 @@ export default class extends Channel {
 
 		if (!['map', 'bw', 'isLlotheo', 'canPutEverywhere', 'loopedBoard'].includes(key)) return;
 
-		await ReversiGames.update({ id: this.gameId }, {
+		await ReversiGames.update(this.gameId!, {
 			[key]: value
 		});
 
-		publishReversiGameStream(this.gameId, 'updateSettings', {
+		publishReversiGameStream(this.gameId!, 'updateSettings', {
 			key: key,
 			value: value
 		});
@@ -61,7 +64,10 @@ export default class extends Channel {
 
 	@autobind
 	private async initForm(form: any) {
-		const game = await ReversiGames.findOne(this.gameId);
+		if (this.user == null) return;
+
+		const game = await ReversiGames.findOne(this.gameId!);
+		if (game == null) throw 'game not found';
 
 		if (game.isStarted) return;
 		if ((game.user1Id !== this.user.id) && (game.user2Id !== this.user.id)) return;
@@ -72,9 +78,9 @@ export default class extends Channel {
 			form2: form
 		};
 
-		await ReversiGames.update({ id: this.gameId }, set);
+		await ReversiGames.update(this.gameId!, set);
 
-		publishReversiGameStream(this.gameId, 'initForm', {
+		publishReversiGameStream(this.gameId!, 'initForm', {
 			userId: this.user.id,
 			form
 		});
@@ -82,7 +88,10 @@ export default class extends Channel {
 
 	@autobind
 	private async updateForm(id: string, value: any) {
-		const game = await ReversiGames.findOne({ id: this.gameId });
+		if (this.user == null) return;
+
+		const game = await ReversiGames.findOne(this.gameId!);
+		if (game == null) throw 'game not found';
 
 		if (game.isStarted) return;
 		if ((game.user1Id !== this.user.id) && (game.user2Id !== this.user.id)) return;
@@ -101,9 +110,9 @@ export default class extends Channel {
 				form1: form
 			};
 
-		await ReversiGames.update({ id: this.gameId }, set);
+		await ReversiGames.update(this.gameId!, set);
 
-		publishReversiGameStream(this.gameId, 'updateForm', {
+		publishReversiGameStream(this.gameId!, 'updateForm', {
 			userId: this.user.id,
 			id,
 			value
@@ -112,8 +121,10 @@ export default class extends Channel {
 
 	@autobind
 	private async message(message: any) {
+		if (this.user == null) return;
+
 		message.id = Math.random();
-		publishReversiGameStream(this.gameId, 'message', {
+		publishReversiGameStream(this.gameId!, 'message', {
 			userId: this.user.id,
 			message
 		});
@@ -121,29 +132,32 @@ export default class extends Channel {
 
 	@autobind
 	private async accept(accept: boolean) {
-		const game = await ReversiGames.findOne(this.gameId);
+		if (this.user == null) return;
+
+		const game = await ReversiGames.findOne(this.gameId!);
+		if (game == null) throw 'game not found';
 
 		if (game.isStarted) return;
 
 		let bothAccepted = false;
 
 		if (game.user1Id === this.user.id) {
-			await ReversiGames.update({ id: this.gameId }, {
+			await ReversiGames.update(this.gameId!, {
 				user1Accepted: accept
 			});
 
-			publishReversiGameStream(this.gameId, 'changeAccepts', {
+			publishReversiGameStream(this.gameId!, 'changeAccepts', {
 				user1: accept,
 				user2: game.user2Accepted
 			});
 
 			if (accept && game.user2Accepted) bothAccepted = true;
 		} else if (game.user2Id === this.user.id) {
-			await ReversiGames.update({ id: this.gameId }, {
+			await ReversiGames.update(this.gameId!, {
 				user2Accepted: accept
 			});
 
-			publishReversiGameStream(this.gameId, 'changeAccepts', {
+			publishReversiGameStream(this.gameId!, 'changeAccepts', {
 				user1: game.user1Accepted,
 				user2: accept
 			});
@@ -156,7 +170,7 @@ export default class extends Channel {
 		if (bothAccepted) {
 			// 3秒後、まだacceptされていたらゲーム開始
 			setTimeout(async () => {
-				const freshGame = await ReversiGames.findOne(this.gameId);
+				const freshGame = await ReversiGames.findOne(this.gameId!);
 				if (freshGame == null || freshGame.isStarted || freshGame.isEnded) return;
 				if (!freshGame.user1Accepted || !freshGame.user2Accepted) return;
 
@@ -175,7 +189,7 @@ export default class extends Channel {
 
 				const map = freshGame.map != null ? freshGame.map : getRandomMap();
 
-				await ReversiGames.update({ id: this.gameId }, {
+				await ReversiGames.update(this.gameId!, {
 					startedAt: new Date(),
 					isStarted: true,
 					black: bw,
@@ -199,22 +213,20 @@ export default class extends Channel {
 						winner = null;
 					}
 
-					await ReversiGames.update({
-						id: this.gameId
-					}, {
+					await ReversiGames.update(this.gameId!, {
 						isEnded: true,
 						winnerId: winner
 					});
 
-					publishReversiGameStream(this.gameId, 'ended', {
+					publishReversiGameStream(this.gameId!, 'ended', {
 						winnerId: winner,
-						game: await ReversiGames.pack(this.gameId, this.user)
+						game: await ReversiGames.pack(this.gameId!, this.user)
 					});
 				}
 				//#endregion
 
-				publishReversiGameStream(this.gameId, 'started',
-					await ReversiGames.pack(this.gameId, this.user));
+				publishReversiGameStream(this.gameId!, 'started',
+					await ReversiGames.pack(this.gameId!, this.user));
 			}, 3000);
 		}
 	}
@@ -222,7 +234,10 @@ export default class extends Channel {
 	// 石を打つ
 	@autobind
 	private async set(pos: number) {
-		const game = await ReversiGames.findOne(this.gameId);
+		if (this.user == null) return;
+
+		const game = await ReversiGames.findOne(this.gameId!);
+		if (game == null) throw 'game not found';
 
 		if (!game.isStarted) return;
 		if (game.isEnded) return;
@@ -267,30 +282,29 @@ export default class extends Channel {
 
 		game.logs.push(log);
 
-		await ReversiGames.update({
-			id: this.gameId
-		}, {
+		await ReversiGames.update(this.gameId!, {
 			crc32,
 			isEnded: o.isEnded,
 			winnerId: winner,
 			logs: game.logs
 		});
 
-		publishReversiGameStream(this.gameId, 'set', Object.assign(log, {
+		publishReversiGameStream(this.gameId!, 'set', Object.assign(log, {
 			next: o.turn
 		}));
 
 		if (o.isEnded) {
-			publishReversiGameStream(this.gameId, 'ended', {
+			publishReversiGameStream(this.gameId!, 'ended', {
 				winnerId: winner,
-				game: await ReversiGames.pack(this.gameId, this.user)
+				game: await ReversiGames.pack(this.gameId!, this.user)
 			});
 		}
 	}
 
 	@autobind
 	private async check(crc32: string) {
-		const game = await ReversiGames.findOne(this.gameId);
+		const game = await ReversiGames.findOne(this.gameId!);
+		if (game == null) throw 'game not found';
 
 		if (!game.isStarted) return;
 
diff --git a/src/server/api/stream/channels/games/reversi.ts b/src/server/api/stream/channels/games/reversi.ts
index 0498e5e017..3db338386a 100644
--- a/src/server/api/stream/channels/games/reversi.ts
+++ b/src/server/api/stream/channels/games/reversi.ts
@@ -11,7 +11,7 @@ export default class extends Channel {
 	@autobind
 	public async init(params: any) {
 		// Subscribe reversi stream
-		this.subscriber.on(`reversiStream:${this.user.id}`, data => {
+		this.subscriber.on(`reversiStream:${this.user!.id}`, data => {
 			this.send(data);
 		});
 	}
@@ -22,7 +22,7 @@ export default class extends Channel {
 			case 'ping':
 				if (body.id == null) return;
 				const matching = await ReversiMatchings.findOne({
-					parentId: this.user.id,
+					parentId: this.user!.id,
 					childId: body.id
 				});
 				if (matching == null) return;
diff --git a/src/server/api/stream/channels/home-timeline.ts b/src/server/api/stream/channels/home-timeline.ts
index 2cece0947f..61960657b4 100644
--- a/src/server/api/stream/channels/home-timeline.ts
+++ b/src/server/api/stream/channels/home-timeline.ts
@@ -17,10 +17,10 @@ export default class extends Channel {
 	@autobind
 	private async onNote(note: any) {
 		// その投稿のユーザーをフォローしていなかったら弾く
-		if (this.user.id !== note.userId && !this.following.includes(note.userId)) return;
+		if (this.user!.id !== note.userId && !this.following.includes(note.userId)) return;
 
 		if (['followers', 'specified'].includes(note.visibility)) {
-			note = await Notes.pack(note.id, this.user, {
+			note = await Notes.pack(note.id, this.user!, {
 				detail: true
 			});
 
@@ -30,13 +30,13 @@ export default class extends Channel {
 		} else {
 			// リプライなら再pack
 			if (note.replyId != null) {
-				note.reply = await Notes.pack(note.replyId, this.user, {
+				note.reply = await Notes.pack(note.replyId, this.user!, {
 					detail: true
 				});
 			}
 			// Renoteなら再pack
 			if (note.renoteId != null) {
-				note.renote = await Notes.pack(note.renoteId, this.user, {
+				note.renote = await Notes.pack(note.renoteId, this.user!, {
 					detail: true
 				});
 			}
diff --git a/src/server/api/stream/channels/hybrid-timeline.ts b/src/server/api/stream/channels/hybrid-timeline.ts
index 30643aeda8..18e6aa8350 100644
--- a/src/server/api/stream/channels/hybrid-timeline.ts
+++ b/src/server/api/stream/channels/hybrid-timeline.ts
@@ -12,7 +12,7 @@ export default class extends Channel {
 	@autobind
 	public async init(params: any) {
 		const meta = await fetchMeta();
-		if (meta.disableLocalTimeline && !this.user.isAdmin && !this.user.isModerator) return;
+		if (meta.disableLocalTimeline && !this.user!.isAdmin && !this.user!.isModerator) return;
 
 		// Subscribe events
 		this.subscriber.on('notesStream', this.onNote);
@@ -22,13 +22,13 @@ export default class extends Channel {
 	private async onNote(note: any) {
 		// 自分自身の投稿 または その投稿のユーザーをフォローしている または ローカルの投稿 の場合だけ
 		if (!(
-			this.user.id === note.userId ||
+			this.user!.id === note.userId ||
 			this.following.includes(note.userId) ||
 			note.user.host == null
 		)) return;
 
 		if (['followers', 'specified'].includes(note.visibility)) {
-			note = await Notes.pack(note.id, this.user, {
+			note = await Notes.pack(note.id, this.user!, {
 				detail: true
 			});
 
@@ -38,13 +38,13 @@ export default class extends Channel {
 		} else {
 			// リプライなら再pack
 			if (note.replyId != null) {
-				note.reply = await Notes.pack(note.replyId, this.user, {
+				note.reply = await Notes.pack(note.replyId, this.user!, {
 					detail: true
 				});
 			}
 			// Renoteなら再pack
 			if (note.renoteId != null) {
-				note.renote = await Notes.pack(note.renoteId, this.user, {
+				note.renote = await Notes.pack(note.renoteId, this.user!, {
 					detail: true
 				});
 			}
diff --git a/src/server/api/stream/channels/main.ts b/src/server/api/stream/channels/main.ts
index 0d9bf3149d..1100f87acb 100644
--- a/src/server/api/stream/channels/main.ts
+++ b/src/server/api/stream/channels/main.ts
@@ -9,10 +9,10 @@ export default class extends Channel {
 
 	@autobind
 	public async init(params: any) {
-		const mute = await Mutings.find({ muterId: this.user.id });
+		const mute = await Mutings.find({ muterId: this.user!.id });
 
 		// Subscribe main stream channel
-		this.subscriber.on(`mainStream:${this.user.id}`, async data => {
+		this.subscriber.on(`mainStream:${this.user!.id}`, async data => {
 			const { type, body } = data;
 
 			switch (type) {
diff --git a/src/server/api/stream/channels/messaging-index.ts b/src/server/api/stream/channels/messaging-index.ts
index 648badc1dc..0c495398ab 100644
--- a/src/server/api/stream/channels/messaging-index.ts
+++ b/src/server/api/stream/channels/messaging-index.ts
@@ -9,7 +9,7 @@ export default class extends Channel {
 	@autobind
 	public async init(params: any) {
 		// Subscribe messaging index stream
-		this.subscriber.on(`messagingIndexStream:${this.user.id}`, data => {
+		this.subscriber.on(`messagingIndexStream:${this.user!.id}`, data => {
 			this.send(data);
 		});
 	}
diff --git a/src/server/api/stream/channels/messaging.ts b/src/server/api/stream/channels/messaging.ts
index b81fbb9d4c..8397f849ff 100644
--- a/src/server/api/stream/channels/messaging.ts
+++ b/src/server/api/stream/channels/messaging.ts
@@ -14,7 +14,7 @@ export default class extends Channel {
 		this.otherpartyId = params.otherparty as string;
 
 		// Subscribe messaging stream
-		this.subscriber.on(`messagingStream:${this.user.id}-${this.otherpartyId}`, data => {
+		this.subscriber.on(`messagingStream:${this.user!.id}-${this.otherpartyId}`, data => {
 			this.send(data);
 		});
 	}
@@ -23,7 +23,7 @@ export default class extends Channel {
 	public onMessage(type: string, body: any) {
 		switch (type) {
 			case 'read':
-				read(this.user.id, this.otherpartyId, body.id);
+				read(this.user!.id, this.otherpartyId, body.id);
 				break;
 		}
 	}
diff --git a/src/server/api/stream/index.ts b/src/server/api/stream/index.ts
index abbd91ec81..f73f3229d5 100644
--- a/src/server/api/stream/index.ts
+++ b/src/server/api/stream/index.ts
@@ -28,13 +28,13 @@ export default class Connection {
 	constructor(
 		wsConnection: websocket.connection,
 		subscriber: EventEmitter,
-		user: User,
-		app: App
+		user: User | null | undefined,
+		app: App | null | undefined
 	) {
 		this.wsConnection = wsConnection;
-		this.user = user;
-		this.app = app;
 		this.subscriber = subscriber;
+		if (user) this.user = user;
+		if (app) this.app = app;
 
 		this.wsConnection.on('message', this.onWsConnectionMessage);
 
@@ -52,6 +52,8 @@ export default class Connection {
 	 */
 	@autobind
 	private async onWsConnectionMessage(data: websocket.IMessage) {
+		if (data.utf8Data == null) return;
+
 		const { type, body } = JSON.parse(data.utf8Data);
 
 		switch (type) {
@@ -89,7 +91,7 @@ export default class Connection {
 	@autobind
 	private onReadNotification(payload: any) {
 		if (!payload.id) return;
-		readNotification(this.user.id, [payload.id]);
+		readNotification(this.user!.id, [payload.id]);
 	}
 
 	/**
@@ -109,7 +111,7 @@ export default class Connection {
 			this.subscriber.on(`noteStream:${payload.id}`, this.onNoteStreamMessage);
 		}
 
-		if (payload.read) {
+		if (payload.read && this.user) {
 			readNote(this.user.id, payload.id);
 		}
 	}
@@ -221,7 +223,7 @@ export default class Connection {
 	private async updateFollowing() {
 		const followings = await Followings.find({
 			where: {
-				followerId: this.user.id
+				followerId: this.user!.id
 			},
 			select: ['followeeId']
 		});
@@ -233,7 +235,7 @@ export default class Connection {
 	private async updateMuting() {
 		const mutings = await Mutings.find({
 			where: {
-				muterId: this.user.id
+				muterId: this.user!.id
 			},
 			select: ['muteeId']
 		});
@@ -247,7 +249,7 @@ export default class Connection {
 	@autobind
 	public dispose() {
 		for (const c of this.channels.filter(c => c.dispose)) {
-			c.dispose();
+			if (c.dispose) c.dispose();
 		}
 
 		if (this.followingClock) clearInterval(this.followingClock);
diff --git a/src/server/file/send-drive-file.ts b/src/server/file/send-drive-file.ts
index f9b067b79c..5da3d79eb5 100644
--- a/src/server/file/send-drive-file.ts
+++ b/src/server/file/send-drive-file.ts
@@ -50,7 +50,7 @@ export default async function(ctx: Koa.BaseContext) {
 			ctx.set('Content-Disposition', contentDisposition('attachment', `${file.name}`));
 		}
 
-		const readable = InternalStorage.read(file.accessKey);
+		const readable = InternalStorage.read(file.accessKey!);
 		readable.on('error', commonReadableHandlerGenerator(ctx));
 		ctx.set('Content-Type', file.type);
 		ctx.body = readable;
diff --git a/src/server/index.ts b/src/server/index.ts
index 9c153f0167..601e288f3b 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -32,7 +32,7 @@ export const serverLogger = new Logger('server', 'gray', false);
 const app = new Koa();
 app.proxy = true;
 
-if (!['production', 'test'].includes(process.env.NODE_ENV)) {
+if (!['production', 'test'].includes(process.env.NODE_ENV || '')) {
 	// Logger
 	app.use(koaLogger(str => {
 		serverLogger.info(str);
diff --git a/src/server/web/docs.ts b/src/server/web/docs.ts
index d9ba14a8ed..374dbf3bd2 100644
--- a/src/server/web/docs.ts
+++ b/src/server/web/docs.ts
@@ -34,14 +34,14 @@ async function genVars(lang: string): Promise<{ [key: string]: any }> {
 	const docs = glob.sync(`src/docs/**/*.${lang}.md`, { cwd });
 	vars['docs'] = {};
 	for (const x of docs) {
-		const [, name] = x.match(/docs\/(.+?)\.(.+?)\.md$/);
+		const [, name] = x.match(/docs\/(.+?)\.(.+?)\.md$/)!;
 		if (vars['docs'][name] == null) {
 			vars['docs'][name] = {
 				name,
 				title: {}
 			};
 		}
-		vars['docs'][name]['title'][lang] = fs.readFileSync(cwd + x, 'utf-8').match(/^# (.+?)\r?\n/)[1];
+		vars['docs'][name]['title'][lang] = fs.readFileSync(cwd + x, 'utf-8').match(/^# (.+?)\r?\n/)![1];
 	}
 
 	vars['kebab'] = (string: string) => string.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/\s+/g, '-').toLowerCase();
@@ -97,7 +97,7 @@ router.get('/*/*', async ctx => {
 	await ctx.render('../../../../src/docs/article', Object.assign({
 		id: doc,
 		html: conv.makeHtml(md),
-		title: md.match(/^# (.+?)\r?\n/)[1],
+		title: md.match(/^# (.+?)\r?\n/)![1],
 		src: `https://github.com/syuilo/misskey/tree/master/src/docs/${doc}.${lang}.md`
 	}, await genVars(lang)));
 
diff --git a/src/server/web/feed.ts b/src/server/web/feed.ts
index 94f0643f75..285c20fcdb 100644
--- a/src/server/web/feed.ts
+++ b/src/server/web/feed.ts
@@ -3,6 +3,7 @@ import config from '../../config';
 import { User } from '../../models/entities/user';
 import { Notes, DriveFiles, UserProfiles } from '../../models';
 import { In } from 'typeorm';
+import { ensure } from '../../prelude/ensure';
 
 export default async function(user: User) {
 	const author: Author = {
@@ -10,7 +11,7 @@ export default async function(user: User) {
 		name: user.name || user.username
 	};
 
-	const profile = await UserProfiles.findOne({ userId: user.id });
+	const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure);
 
 	const notes = await Notes.find({
 		where: {
@@ -47,9 +48,9 @@ export default async function(user: User) {
 			title: `New note by ${author.name}`,
 			link: `${config.url}/notes/${note.id}`,
 			date: note.createdAt,
-			description: note.cw,
-			content: note.text,
-			image: file ? DriveFiles.getPublicUrl(file) : null
+			description: note.cw || undefined,
+			content: note.text || undefined,
+			image: file ? DriveFiles.getPublicUrl(file) : undefined
 		});
 	}
 
diff --git a/src/server/web/index.ts b/src/server/web/index.ts
index d1a15e3929..5cadf1b124 100644
--- a/src/server/web/index.ts
+++ b/src/server/web/index.ts
@@ -19,6 +19,7 @@ import config from '../../config';
 import { Users, Notes, Emojis, UserProfiles } from '../../models';
 import parseAcct from '../../misc/acct/parse';
 import getNoteSummary from '../../misc/get-note-summary';
+import { ensure } from '../../prelude/ensure';
 
 const client = `${__dirname}/../../client/`;
 
@@ -149,11 +150,9 @@ router.get('/@:user', async (ctx, next) => {
 		usernameLower: username.toLowerCase(),
 		host
 	});
-	const profile = await UserProfiles.findOne({
-		userId: user.id
-	});
 
 	if (user != null) {
+		const profile = await UserProfiles.findOne(user.id).then(ensure);
 		const meta = await fetchMeta();
 		await ctx.render('user', {
 			user, profile,
diff --git a/src/server/web/url-preview.ts b/src/server/web/url-preview.ts
index aed475e6ff..7d0080b4d2 100644
--- a/src/server/web/url-preview.ts
+++ b/src/server/web/url-preview.ts
@@ -43,7 +43,7 @@ module.exports = async (ctx: Koa.BaseContext) => {
 	}
 };
 
-function wrap(url: string): string {
+function wrap(url?: string): string | null {
 	return url != null
 		? url.match(/^https?:\/\//)
 			? `${config.url}/proxy/preview.jpg?${query({
diff --git a/src/server/well-known.ts b/src/server/well-known.ts
index 7c5684d2ce..d29b7a8888 100644
--- a/src/server/well-known.ts
+++ b/src/server/well-known.ts
@@ -54,9 +54,9 @@ router.get(webFingerPath, async ctx => {
 
 	const generateQuery = (resource: string) =>
 		resource.startsWith(`${config.url.toLowerCase()}/users/`) ?
-			fromId(resource.split('/').pop()) :
+			fromId(resource.split('/').pop()!) :
 			fromAcct(parseAcct(
-				resource.startsWith(`${config.url.toLowerCase()}/@`) ? resource.split('/').pop() :
+				resource.startsWith(`${config.url.toLowerCase()}/@`) ? resource.split('/').pop()! :
 				resource.startsWith('acct:') ? resource.slice('acct:'.length) :
 				resource));
 
diff --git a/src/services/blocking/create.ts b/src/services/blocking/create.ts
index 79ca0d59f1..def4f33585 100644
--- a/src/services/blocking/create.ts
+++ b/src/services/blocking/create.ts
@@ -66,7 +66,7 @@ async function cancelRequest(follower: User, followee: User) {
 
 	// リモートからフォローリクエストを受けていたらReject送信
 	if (Users.isRemoteUser(follower) && Users.isLocalUser(followee)) {
-		const content = renderActivity(renderReject(renderFollow(follower, followee, request.requestId), followee));
+		const content = renderActivity(renderReject(renderFollow(follower, followee, request.requestId!), followee));
 		deliver(followee, content, follower.inbox);
 	}
 }
diff --git a/src/services/chart/core.ts b/src/services/chart/core.ts
index 2a60b1a0a3..0a9ec8dae0 100644
--- a/src/services/chart/core.ts
+++ b/src/services/chart/core.ts
@@ -84,7 +84,7 @@ export default abstract class Chart<T extends Record<string, any>> {
 				}
 			}
 		};
-		flatColumns(schema.properties);
+		flatColumns(schema.properties!);
 		return columns;
 	}
 
@@ -182,7 +182,7 @@ export default abstract class Chart<T extends Record<string, any>> {
 	}
 
 	@autobind
-	private getNewLog(latest?: T): T {
+	private getNewLog(latest: T | null): T {
 		const log = latest ? this.genNewLog(latest) : {};
 		const flatColumns = (x: Obj, path?: string) => {
 			for (const [k, v] of Object.entries(x)) {
@@ -196,7 +196,7 @@ export default abstract class Chart<T extends Record<string, any>> {
 				}
 			}
 		};
-		flatColumns(this.schema.properties);
+		flatColumns(this.schema.properties!);
 		return log as T;
 	}
 
@@ -213,7 +213,7 @@ export default abstract class Chart<T extends Record<string, any>> {
 	}
 
 	@autobind
-	private getLatestLog(span: Span, group: string = null): Promise<Log> {
+	private getLatestLog(span: Span, group: string | null = null): Promise<Log | null> {
 		return this.repository.findOne({
 			group: group,
 			span: span
@@ -221,17 +221,17 @@ export default abstract class Chart<T extends Record<string, any>> {
 			order: {
 				date: -1
 			}
-		});
+		}).then(x => x || null);
 	}
 
 	@autobind
-	private async getCurrentLog(span: Span, group: string = null): Promise<Log> {
+	private async getCurrentLog(span: Span, group: string | null = null): Promise<Log> {
 		const [y, m, d, h] = this.getCurrentDate();
 
 		const current =
 			span == 'day' ? utc([y, m, d]) :
 			span == 'hour' ? utc([y, m, d, h]) :
-			null;
+			null as never;
 
 		// 現在(今日または今のHour)のログ
 		const currentLog = await this.repository.findOne({
@@ -285,7 +285,7 @@ export default abstract class Chart<T extends Record<string, any>> {
 			// 並列動作している他のチャートエンジンプロセスと処理が重なる場合がある
 			// その場合は再度最も新しいログを持ってくる
 			if (isDuplicateKeyValueError(e)) {
-				log = await this.getLatestLog(span, group);
+				log = await this.getLatestLog(span, group) as Log;
 			} else {
 				logger.error(e);
 				throw e;
@@ -296,17 +296,17 @@ export default abstract class Chart<T extends Record<string, any>> {
 	}
 
 	@autobind
-	protected commit(query: Record<string, Function>, group: string = null, uniqueKey?: string, uniqueValue?: string): Promise<any> {
+	protected commit(query: Record<string, Function>, group: string | null = null, uniqueKey?: string, uniqueValue?: string): Promise<any> {
 		const update = async (log: Log) => {
 			// ユニークインクリメントの場合、指定のキーに指定の値が既に存在していたら弾く
 			if (
-				uniqueKey &&
+				uniqueKey && log.unique &&
 				log.unique[uniqueKey] &&
 				log.unique[uniqueKey].includes(uniqueValue)
 			) return;
 
 			// ユニークインクリメントの指定のキーに値を追加
-			if (uniqueKey) {
+			if (uniqueKey && log.unique) {
 				if (log.unique[uniqueKey]) {
 					const sql = `jsonb_set("unique", '{${uniqueKey}}', ("unique"->>'${uniqueKey}')::jsonb || '["${uniqueValue}"]'::jsonb)`;
 					query['unique'] = () => sql;
@@ -331,23 +331,23 @@ export default abstract class Chart<T extends Record<string, any>> {
 	}
 
 	@autobind
-	protected async inc(inc: DeepPartial<T>, group: string = null): Promise<void> {
+	protected async inc(inc: DeepPartial<T>, group: string | null = null): Promise<void> {
 		await this.commit(Chart.convertQuery(inc as any), group);
 	}
 
 	@autobind
-	protected async incIfUnique(inc: DeepPartial<T>, key: string, value: string, group: string = null): Promise<void> {
+	protected async incIfUnique(inc: DeepPartial<T>, key: string, value: string, group: string | null = null): Promise<void> {
 		await this.commit(Chart.convertQuery(inc as any), group, key, value);
 	}
 
 	@autobind
-	public async getChart(span: Span, range: number, group: string = null): Promise<ArrayValue<T>> {
+	public async getChart(span: Span, range: number, group: string | null = null): Promise<ArrayValue<T>> {
 		const [y, m, d, h] = this.getCurrentDate();
 
 		const gt =
 			span == 'day' ? utc([y, m, d]).subtract(range, 'days') :
 			span == 'hour' ? utc([y, m, d, h]).subtract(range, 'hours') :
-			null;
+			null as never;
 
 		// ログ取得
 		let logs = await this.repository.find({
@@ -404,7 +404,7 @@ export default abstract class Chart<T extends Record<string, any>> {
 			const current =
 				span == 'day' ? utc([y, m, d]).subtract(i, 'days') :
 				span == 'hour' ? utc([y, m, d, h]).subtract(i, 'hours') :
-				null;
+				null as never;
 
 			const log = logs.find(l => utc(l.date * 1000).isSame(current));
 
@@ -452,8 +452,8 @@ export function convertLog(logSchema: Schema): Schema {
 			type: 'number'
 		};
 	} else if (v.type === 'object') {
-		for (const k of Object.keys(v.properties)) {
-			v.properties[k] = convertLog(v.properties[k]);
+		for (const k of Object.keys(v.properties!)) {
+			v.properties![k] = convertLog(v.properties![k]);
 		}
 	}
 	return v;
diff --git a/src/services/create-notification.ts b/src/services/create-notification.ts
index bcb8214c56..5bff8adfd4 100644
--- a/src/services/create-notification.ts
+++ b/src/services/create-notification.ts
@@ -46,6 +46,7 @@ export async function createNotification(
 	// 2秒経っても(今回作成した)通知が既読にならなかったら「未読の通知がありますよ」イベントを発行する
 	setTimeout(async () => {
 		const fresh = await Notifications.findOne(notification.id);
+		if (fresh == null) return; // 既に削除されているかもしれない
 		if (!fresh.isRead) {
 			//#region ただしミュートしているユーザーからの通知なら無視
 			const mutings = await Mutings.find({
diff --git a/src/services/drive/add-file.ts b/src/services/drive/add-file.ts
index b83c3558d3..94b97fed61 100644
--- a/src/services/drive/add-file.ts
+++ b/src/services/drive/add-file.ts
@@ -55,10 +55,10 @@ async function save(file: DriveFile, path: string, name: string, type: string, h
 		const url = `${ baseUrl }/${ key }`;
 
 		// for alts
-		let webpublicKey: string = null;
-		let webpublicUrl: string = null;
-		let thumbnailKey: string = null;
-		let thumbnailUrl: string = null;
+		let webpublicKey: string | null = null;
+		let webpublicUrl: string | null = null;
+		let thumbnailKey: string | null = null;
+		let thumbnailUrl: string | null = null;
 		//#endregion
 
 		//#region Uploads
@@ -106,8 +106,8 @@ async function save(file: DriveFile, path: string, name: string, type: string, h
 
 		const url = InternalStorage.saveFromPath(accessKey, path);
 
-		let thumbnailUrl: string;
-		let webpublicUrl: string;
+		let thumbnailUrl: string | null = null;
+		let webpublicUrl: string | null = null;
 
 		if (alts.thumbnail) {
 			thumbnailUrl = InternalStorage.saveFromBuffer(thumbnailAccessKey, alts.thumbnail.data);
@@ -143,7 +143,7 @@ async function save(file: DriveFile, path: string, name: string, type: string, h
  */
 export async function generateAlts(path: string, type: string, generateWeb: boolean) {
 	// #region webpublic
-	let webpublic: IImage;
+	let webpublic: IImage | null = null;
 
 	if (generateWeb) {
 		logger.info(`creating web image`);
@@ -163,7 +163,7 @@ export async function generateAlts(path: string, type: string, generateWeb: bool
 	// #endregion webpublic
 
 	// #region thumbnail
-	let thumbnail: IImage;
+	let thumbnail: IImage | null = null;
 
 	if (['image/jpeg', 'image/webp'].includes(type)) {
 		thumbnail = await ConvertToJpeg(path, 498, 280);
@@ -188,7 +188,7 @@ export async function generateAlts(path: string, type: string, generateWeb: bool
  * Upload to ObjectStorage
  */
 async function upload(key: string, stream: fs.ReadStream | Buffer, type: string, filename?: string) {
-	const minio = new Minio.Client(config.drive.config);
+	const minio = new Minio.Client(config.drive!.config);
 
 	const metadata = {
 		'Content-Type': type,
@@ -197,7 +197,7 @@ async function upload(key: string, stream: fs.ReadStream | Buffer, type: string,
 
 	if (filename) metadata['Content-Disposition'] = contentDisposition('inline', filename);
 
-	await minio.putObject(config.drive.bucket, key, stream, null, metadata);
+	await minio.putObject(config.drive!.bucket!, key, stream, undefined, metadata);
 }
 
 async function deleteOldFile(user: IRemoteUser) {
@@ -232,14 +232,14 @@ async function deleteOldFile(user: IRemoteUser) {
 export default async function(
 	user: User,
 	path: string,
-	name: string = null,
-	comment: string = null,
+	name: string | null = null,
+	comment: string | null = null,
 	folderId: any = null,
 	force: boolean = false,
 	isLink: boolean = false,
-	url: string = null,
-	uri: string = null,
-	sensitive: boolean = null
+	url: string | null = null,
+	uri: string | null = null,
+	sensitive: boolean | null = null
 ): Promise<DriveFile> {
 	// Calc md5 hash
 	const calcHash = new Promise<string>((res, rej) => {
@@ -300,7 +300,7 @@ export default async function(
 				throw 'no-free-space';
 			} else {
 				// (アバターまたはバナーを含まず)最も古いファイルを削除する
-				deleteOldFile(user);
+				deleteOldFile(user as IRemoteUser);
 			}
 		}
 	}
@@ -378,7 +378,7 @@ export default async function(
 	file.comment = comment;
 	file.properties = properties;
 	file.isLink = isLink;
-	file.isSensitive = Users.isLocalUser(user) && profile.alwaysMarkNsfw ? true :
+	file.isSensitive = Users.isLocalUser(user) && profile!.alwaysMarkNsfw ? true :
 		(sensitive !== null && sensitive !== undefined)
 			? sensitive
 			: false;
@@ -411,7 +411,7 @@ export default async function(
 				file = await DriveFiles.findOne({
 					uri: file.uri,
 					userId: user.id
-				});
+				}) as DriveFile;
 			} else {
 				logger.error(e);
 				throw e;
diff --git a/src/services/drive/delete-file.ts b/src/services/drive/delete-file.ts
index b7fa99391e..bba453b982 100644
--- a/src/services/drive/delete-file.ts
+++ b/src/services/drive/delete-file.ts
@@ -7,31 +7,31 @@ import { driveChart, perUserDriveChart, instanceChart } from '../chart';
 
 export default async function(file: DriveFile, isExpired = false) {
 	if (file.storedInternal) {
-		InternalStorage.del(file.accessKey);
+		InternalStorage.del(file.accessKey!);
 
 		if (file.thumbnailUrl) {
-			InternalStorage.del(file.thumbnailAccessKey);
+			InternalStorage.del(file.thumbnailAccessKey!);
 		}
 
 		if (file.webpublicUrl) {
-			InternalStorage.del(file.webpublicAccessKey);
+			InternalStorage.del(file.webpublicAccessKey!);
 		}
 	} else if (!file.isLink) {
-		const minio = new Minio.Client(config.drive.config);
+		const minio = new Minio.Client(config.drive!.config);
 
-		await minio.removeObject(config.drive.bucket, file.accessKey);
+		await minio.removeObject(config.drive!.bucket!, file.accessKey!);
 
 		if (file.thumbnailUrl) {
-			await minio.removeObject(config.drive.bucket, file.thumbnailAccessKey);
+			await minio.removeObject(config.drive!.bucket!, file.thumbnailAccessKey!);
 		}
 
 		if (file.webpublicUrl) {
-			await minio.removeObject(config.drive.bucket, file.webpublicAccessKey);
+			await minio.removeObject(config.drive!.bucket!, file.webpublicAccessKey!);
 		}
 	}
 
 	// リモートファイル期限切れ削除後は直リンクにする
-	if (isExpired && file.userHost !== null) {
+	if (isExpired && file.userHost !== null && file.uri != null) {
 		DriveFiles.update(file.id, {
 			isLink: true,
 			url: file.uri,
diff --git a/src/services/drive/image-processor.ts b/src/services/drive/image-processor.ts
index 3c538390b0..89ac331ca1 100644
--- a/src/services/drive/image-processor.ts
+++ b/src/services/drive/image-processor.ts
@@ -2,7 +2,7 @@ import * as sharp from 'sharp';
 
 export type IImage = {
 	data: Buffer;
-	ext: string;
+	ext: string | null;
 	type: string;
 };
 
diff --git a/src/services/drive/upload-from-url.ts b/src/services/drive/upload-from-url.ts
index a7fe1fbd26..bfe8c5c3b2 100644
--- a/src/services/drive/upload-from-url.ts
+++ b/src/services/drive/upload-from-url.ts
@@ -1,4 +1,3 @@
-import * as URL from 'url';
 import create from './add-file';
 import { User } from '../../models/entities/user';
 import { driveLogger } from './logger';
@@ -13,14 +12,14 @@ const logger = driveLogger.createSubLogger('downloader');
 export default async (
 	url: string,
 	user: User,
-	folderId: DriveFolder['id'] = null,
-	uri: string = null,
+	folderId: DriveFolder['id'] | null = null,
+	uri: string | null = null,
 	sensitive = false,
 	force = false,
 	link = false
 ): Promise<DriveFile> => {
-	let name = URL.parse(url).pathname.split('/').pop();
-	if (!DriveFiles.validateFileName(name)) {
+	let name = new URL(url).pathname.split('/').pop() || null;
+	if (name == null || !DriveFiles.validateFileName(name)) {
 		name = null;
 	}
 
@@ -50,6 +49,6 @@ export default async (
 	if (error) {
 		throw error;
 	} else {
-		return driveFile;
+		return driveFile!;
 	}
 };
diff --git a/src/services/following/create.ts b/src/services/following/create.ts
index 57bb61fd92..b69dfe42b9 100644
--- a/src/services/following/create.ts
+++ b/src/services/following/create.ts
@@ -14,6 +14,7 @@ import { instanceChart, perUserFollowingChart } from '../chart';
 import { genId } from '../../misc/gen-id';
 import { createNotification } from '../create-notification';
 import { isDuplicateKeyValueError } from '../../misc/is-duplicate-key-value-error';
+import { ensure } from '../../prelude/ensure';
 
 const logger = new Logger('following/create');
 
@@ -115,7 +116,7 @@ export default async function(follower: User, followee: User, requestId?: string
 		if (blocked != null) throw new IdentifiableError('3338392a-f764-498d-8855-db939dcf8c48', 'blocked');
 	}
 
-	const followeeProfile = await UserProfiles.findOne({ userId: followee.id });
+	const followeeProfile = await UserProfiles.findOne(followee.id).then(ensure);
 
 	// フォロー対象が鍵アカウントである or
 	// フォロワーがBotであり、フォロー対象がBotからのフォローに慎重である or
diff --git a/src/services/following/requests/accept-all.ts b/src/services/following/requests/accept-all.ts
index b61c31a513..70e7448aad 100644
--- a/src/services/following/requests/accept-all.ts
+++ b/src/services/following/requests/accept-all.ts
@@ -1,6 +1,7 @@
 import accept from './accept';
 import { User } from '../../../models/entities/user';
 import { FollowRequests, Users } from '../../../models';
+import { ensure } from '../../../prelude/ensure';
 
 /**
  * 指定したユーザー宛てのフォローリクエストをすべて承認
@@ -12,7 +13,7 @@ export default async function(user: User) {
 	});
 
 	for (const request of requests) {
-		const follower = await Users.findOne(request.followerId);
+		const follower = await Users.findOne(request.followerId).then(ensure);
 		accept(user, follower);
 	}
 }
diff --git a/src/services/following/requests/accept.ts b/src/services/following/requests/accept.ts
index 0be8e24e1a..1397514ad1 100644
--- a/src/services/following/requests/accept.ts
+++ b/src/services/following/requests/accept.ts
@@ -16,7 +16,7 @@ export default async function(followee: User, follower: User) {
 	await insertFollowingDoc(followee, follower);
 
 	if (Users.isRemoteUser(follower) && request) {
-		const content = renderActivity(renderAccept(renderFollow(follower, followee, request.requestId), followee as ILocalUser));
+		const content = renderActivity(renderAccept(renderFollow(follower, followee, request.requestId!), followee as ILocalUser));
 		deliver(followee as ILocalUser, content, follower.inbox);
 	}
 
diff --git a/src/services/following/requests/reject.ts b/src/services/following/requests/reject.ts
index c590edcfd8..d5b5e48c41 100644
--- a/src/services/following/requests/reject.ts
+++ b/src/services/following/requests/reject.ts
@@ -13,7 +13,7 @@ export default async function(followee: User, follower: User) {
 			followerId: follower.id
 		});
 
-		const content = renderActivity(renderReject(renderFollow(follower, followee, request.requestId), followee as ILocalUser));
+		const content = renderActivity(renderReject(renderFollow(follower, followee, request!.requestId!), followee as ILocalUser));
 		deliver(followee as ILocalUser, content, follower.inbox);
 	}
 
diff --git a/src/services/i/pin.ts b/src/services/i/pin.ts
index 4e43421bdc..f5c957c742 100644
--- a/src/services/i/pin.ts
+++ b/src/services/i/pin.ts
@@ -77,9 +77,8 @@ export async function removePinned(user: User, noteId: Note['id']) {
 }
 
 export async function deliverPinnedChange(userId: User['id'], noteId: Note['id'], isAddition: boolean) {
-	const user = await Users.findOne({
-		id: userId
-	});
+	const user = await Users.findOne(userId);
+	if (user == null) throw 'user not found';
 
 	if (!Users.isLocalUser(user)) return;
 
@@ -108,14 +107,8 @@ async function CreateRemoteInboxes(user: ILocalUser): Promise<string[]> {
 	const queue: string[] = [];
 
 	for (const following of followers) {
-		const follower = {
-			host: following.followerHost,
-			inbox: following.followerInbox,
-			sharedInbox: following.followerSharedInbox,
-		};
-
-		if (follower.host !== null) {
-			const inbox = follower.sharedInbox || follower.inbox;
+		if (Followings.isRemoteFollower(following)) {
+			const inbox = following.followerSharedInbox || following.followerInbox;
 			if (!queue.includes(inbox)) queue.push(inbox);
 		}
 	}
diff --git a/src/services/i/update.ts b/src/services/i/update.ts
index 7dba472e78..2bb5c7a100 100644
--- a/src/services/i/update.ts
+++ b/src/services/i/update.ts
@@ -6,9 +6,8 @@ import { User } from '../../models/entities/user';
 import { renderPerson } from '../../remote/activitypub/renderer/person';
 
 export async function publishToFollowers(userId: User['id']) {
-	const user = await Users.findOne({
-		id: userId
-	});
+	const user = await Users.findOne(userId);
+	if (user == null) throw 'user not found';
 
 	const followers = await Followings.find({
 		followeeId: user.id
@@ -19,7 +18,7 @@ export async function publishToFollowers(userId: User['id']) {
 	// フォロワーがリモートユーザーかつ投稿者がローカルユーザーならUpdateを配信
 	if (Users.isLocalUser(user)) {
 		for (const following of followers) {
-			if (following.followerHost !== null) {
+			if (Followings.isRemoteFollower(following)) {
 				const inbox = following.followerSharedInbox || following.followerInbox;
 				if (!queue.includes(inbox)) queue.push(inbox);
 			}
diff --git a/src/services/logger.ts b/src/services/logger.ts
index e6a54e626d..190bbdd253 100644
--- a/src/services/logger.ts
+++ b/src/services/logger.ts
@@ -9,14 +9,14 @@ import { genId } from '../misc/gen-id';
 
 type Domain = {
 	name: string;
-	color: string;
+	color?: string;
 };
 
 type Level = 'error' | 'success' | 'warning' | 'debug' | 'info';
 
 export default class Logger {
 	private domain: Domain;
-	private parentLogger: Logger;
+	private parentLogger: Logger | null = null;
 	private store: boolean;
 
 	constructor(domain: string, color?: string, store = true) {
@@ -33,7 +33,7 @@ export default class Logger {
 		return logger;
 	}
 
-	private log(level: Level, message: string, data: Record<string, any>, important = false, subDomains: Domain[] = [], store = true): void {
+	private log(level: Level, message: string, data?: Record<string, any> | null, important = false, subDomains: Domain[] = [], store = true): void {
 		if (program.quiet) return;
 		if (!this.store) store = false;
 
@@ -80,7 +80,7 @@ export default class Logger {
 		}
 	}
 
-	public error(x: string | Error, data?: Record<string, any>, important = false): void { // 実行を継続できない状況で使う
+	public error(x: string | Error, data?: Record<string, any> | null, important = false): void { // 実行を継続できない状況で使う
 		if (x instanceof Error) {
 			data = data || {};
 			data.e = x;
@@ -90,21 +90,21 @@ export default class Logger {
 		}
 	}
 
-	public warn(message: string, data?: Record<string, any>, important = false): void { // 実行を継続できるが改善すべき状況で使う
+	public warn(message: string, data?: Record<string, any> | null, important = false): void { // 実行を継続できるが改善すべき状況で使う
 		this.log('warning', message, data, important);
 	}
 
-	public succ(message: string, data?: Record<string, any>, important = false): void { // 何かに成功した状況で使う
+	public succ(message: string, data?: Record<string, any> | null, important = false): void { // 何かに成功した状況で使う
 		this.log('success', message, data, important);
 	}
 
-	public debug(message: string, data?: Record<string, any>, important = false): void { // デバッグ用に使う(開発者に必要だが利用者に不要な情報)
+	public debug(message: string, data?: Record<string, any> | null, important = false): void { // デバッグ用に使う(開発者に必要だが利用者に不要な情報)
 		if (process.env.NODE_ENV != 'production' || program.verbose) {
 			this.log('debug', message, data, important);
 		}
 	}
 
-	public info(message: string, data?: Record<string, any>, important = false): void { // それ以外
+	public info(message: string, data?: Record<string, any> | null, important = false): void { // それ以外
 		this.log('info', message, data, important);
 	}
 }
diff --git a/src/services/note/create.ts b/src/services/note/create.ts
index 6906bc71ce..9c5989696a 100644
--- a/src/services/note/create.ts
+++ b/src/services/note/create.ts
@@ -10,7 +10,7 @@ import { parse } from '../../mfm/parse';
 import { resolveUser } from '../../remote/resolve-user';
 import config from '../../config';
 import { updateHashtag } from '../update-hashtag';
-import { erase, concat } from '../../prelude/array';
+import { concat } from '../../prelude/array';
 import insertNoteUnread from './unread';
 import { registerOrFetchInstanceDoc } from '../register-or-fetch-instance-doc';
 import extractMentions from '../../misc/extract-mentions';
@@ -27,6 +27,7 @@ import { notesChart, perUserNotesChart, activeUsersChart, instanceChart } from '
 import { Poll, IPoll } from '../../models/entities/poll';
 import { createNotification } from '../create-notification';
 import { isDuplicateKeyValueError } from '../../misc/is-duplicate-key-value-error';
+import { ensure } from '../../prelude/ensure';
 
 type NotificationType = 'reply' | 'renote' | 'quote' | 'mention';
 
@@ -83,25 +84,25 @@ class NotificationManager {
 }
 
 type Option = {
-	createdAt?: Date;
-	name?: string;
-	text?: string;
-	reply?: Note;
-	renote?: Note;
-	files?: DriveFile[];
-	geo?: any;
-	poll?: IPoll;
-	viaMobile?: boolean;
-	localOnly?: boolean;
-	cw?: string;
+	createdAt?: Date | null;
+	name?: string | null;
+	text?: string | null;
+	reply?: Note | null;
+	renote?: Note | null;
+	files?: DriveFile[] | null;
+	geo?: any | null;
+	poll?: IPoll | null;
+	viaMobile?: boolean | null;
+	localOnly?: boolean | null;
+	cw?: string | null;
 	visibility?: string;
-	visibleUsers?: User[];
-	apMentions?: User[];
-	apHashtags?: string[];
-	apEmojis?: string[];
-	questionUri?: string;
-	uri?: string;
-	app?: App;
+	visibleUsers?: User[] | null;
+	apMentions?: User[] | null;
+	apHashtags?: string[] | null;
+	apEmojis?: string[] | null;
+	questionUri?: string | null;
+	uri?: string | null;
+	app?: App | null;
 };
 
 export default async (user: User, data: Option, silent = false) => new Promise<Note>(async (res, rej) => {
@@ -117,10 +118,6 @@ export default async (user: User, data: Option, silent = false) => new Promise<N
 		data.visibility = 'home';
 	}
 
-	if (data.visibleUsers) {
-		data.visibleUsers = erase(null, data.visibleUsers);
-	}
-
 	// Renote対象が「ホームまたは全体」以外の公開範囲ならreject
 	if (data.renote && data.renote.visibility != 'public' && data.renote.visibility != 'home') {
 		return rej('Renote target is not public or home');
@@ -156,10 +153,10 @@ export default async (user: User, data: Option, silent = false) => new Promise<N
 
 	// Parse MFM if needed
 	if (!tags || !emojis || !mentionedUsers) {
-		const tokens = data.text ? parse(data.text) : [];
-		const cwTokens = data.cw ? parse(data.cw) : [];
+		const tokens = data.text ? parse(data.text)! : [];
+		const cwTokens = data.cw ? parse(data.cw)! : [];
 		const choiceTokens = data.poll && data.poll.choices
-			? concat(data.poll.choices.map(choice => parse(choice)))
+			? concat(data.poll.choices.map(choice => parse(choice)!))
 			: [];
 
 		const combinedTokens = tokens.concat(cwTokens).concat(choiceTokens);
@@ -173,19 +170,21 @@ export default async (user: User, data: Option, silent = false) => new Promise<N
 
 	tags = tags.filter(tag => tag.length <= 100);
 
-	if (data.reply && (user.id !== data.reply.userId) && !mentionedUsers.some(u => u.id === data.reply.userId)) {
-		mentionedUsers.push(await Users.findOne(data.reply.userId));
+	if (data.reply && (user.id !== data.reply.userId) && !mentionedUsers.some(u => u.id === data.reply!.userId)) {
+		mentionedUsers.push(await Users.findOne(data.reply.userId).then(ensure));
 	}
 
 	if (data.visibility == 'specified') {
+		if (data.visibleUsers == null) throw 'invalid param';
+
 		for (const u of data.visibleUsers) {
 			if (!mentionedUsers.some(x => x.id === u.id)) {
 				mentionedUsers.push(u);
 			}
 		}
 
-		if (data.reply && !data.visibleUsers.some(x => x.id === data.reply.userId)) {
-			data.visibleUsers.push(await Users.findOne(data.reply.userId));
+		if (data.reply && !data.visibleUsers.some(x => x.id === data.reply!.userId)) {
+			data.visibleUsers.push(await Users.findOne(data.reply.userId).then(ensure));
 		}
 	}
 
@@ -215,6 +214,8 @@ export default async (user: User, data: Option, silent = false) => new Promise<N
 
 	// 未読通知を作成
 	if (data.visibility == 'specified') {
+		if (data.visibleUsers == null) throw 'invalid param';
+
 		for (const u of data.visibleUsers) {
 			insertNoteUnread(u, note, true);
 		}
@@ -252,7 +253,7 @@ export default async (user: User, data: Option, silent = false) => new Promise<N
 		deliverNoteToMentionedRemoteUsers(mentionedUsers, user, noteActivity);
 	}
 
-	const profile = await UserProfiles.findOne({ userId: user.id });
+	const profile = await UserProfiles.findOne({ userId: user.id }).then(ensure);
 
 	// If has in reply to note
 	if (data.reply) {
@@ -321,18 +322,18 @@ function incRenoteCount(renote: Note) {
 	Notes.increment({ id: renote.id }, 'score', 1);
 }
 
-async function publish(user: User, note: Note, reply: Note, renote: Note, noteActivity: any) {
+async function publish(user: User, note: Note, reply: Note | null | undefined, renote: Note | null | undefined, noteActivity: any) {
 	if (Users.isLocalUser(user)) {
 		// 投稿がリプライかつ投稿者がローカルユーザーかつリプライ先の投稿の投稿者がリモートユーザーなら配送
 		if (reply && reply.userHost !== null) {
-			Users.findOne(reply.userId).then(u => {
+			Users.findOne(reply.userId).then(ensure).then(u => {
 				deliver(user, noteActivity, u.inbox);
 			});
 		}
 
 		// 投稿がRenoteかつ投稿者がローカルユーザーかつRenote元の投稿の投稿者がリモートユーザーなら配送
 		if (renote && renote.userHost !== null) {
-			Users.findOne(renote.userId).then(u => {
+			Users.findOne(renote.userId).then(ensure).then(u => {
 				deliver(user, noteActivity, u.inbox);
 			});
 		}
@@ -340,14 +341,14 @@ async function publish(user: User, note: Note, reply: Note, renote: Note, noteAc
 
 	if (['public', 'home', 'followers'].includes(note.visibility)) {
 		// フォロワーに配信
-		publishToFollowers(note, user, noteActivity, reply);
+		publishToFollowers(note, user, noteActivity);
 	}
 }
 
 async function insertNote(user: User, data: Option, tags: string[], emojis: string[], mentionedUsers: User[]) {
 	const insert = new Note({
-		id: genId(data.createdAt),
-		createdAt: data.createdAt,
+		id: genId(data.createdAt!),
+		createdAt: data.createdAt!,
 		fileIds: data.files ? data.files.map(file => file.id) : [],
 		replyId: data.reply ? data.reply.id : null,
 		renoteId: data.renote ? data.renote.id : null,
@@ -358,8 +359,8 @@ async function insertNote(user: User, data: Option, tags: string[], emojis: stri
 		tags: tags.map(tag => tag.toLowerCase()),
 		emojis,
 		userId: user.id,
-		viaMobile: data.viaMobile,
-		localOnly: data.localOnly,
+		viaMobile: data.viaMobile!,
+		localOnly: data.localOnly!,
 		geo: data.geo || null,
 		appId: data.app ? data.app.id : null,
 		visibility: data.visibility as any,
@@ -401,10 +402,10 @@ async function insertNote(user: User, data: Option, tags: string[], emojis: stri
 
 				const poll = new Poll({
 					noteId: note.id,
-					choices: data.poll.choices,
-					expiresAt: data.poll.expiresAt,
-					multiple: data.poll.multiple,
-					votes: new Array(data.poll.choices.length).fill(0),
+					choices: data.poll!.choices,
+					expiresAt: data.poll!.expiresAt,
+					multiple: data.poll!.multiple,
+					votes: new Array(data.poll!.choices.length).fill(0),
 					noteVisibility: note.visibility,
 					userId: user.id,
 					userHost: user.host
@@ -416,7 +417,7 @@ async function insertNote(user: User, data: Option, tags: string[], emojis: stri
 			note = await Notes.save(insert);
 		}
 
-		return note;
+		return note!;
 	} catch (e) {
 		// duplicate key error
 		if (isDuplicateKeyValueError(e)) {
@@ -434,7 +435,7 @@ async function insertNote(user: User, data: Option, tags: string[], emojis: stri
 function index(note: Note) {
 	if (note.text == null || config.elasticsearch == null) return;
 
-	es.index({
+	es!.index({
 		index: 'misskey',
 		type: 'note',
 		id: note.id.toString(),
@@ -466,7 +467,7 @@ async function notifyToWatchersOfReplyee(reply: Note, user: User, nm: Notificati
 	}
 }
 
-async function publishToFollowers(note: Note, user: User, noteActivity: any, reply: Note) {
+async function publishToFollowers(note: Note, user: User, noteActivity: any) {
 	const followers = await Followings.find({
 		followeeId: note.userId
 	});
@@ -474,7 +475,7 @@ async function publishToFollowers(note: Note, user: User, noteActivity: any, rep
 	const queue: string[] = [];
 
 	for (const following of followers) {
-		if (following.followerHost !== null) {
+		if (Followings.isRemoteFollower(following)) {
 			// フォロワーがリモートユーザーかつ投稿者がローカルユーザーなら投稿を配信
 			if (Users.isLocalUser(user)) {
 				const inbox = following.followerSharedInbox || following.followerInbox;
@@ -523,11 +524,9 @@ async function extractMentionedUsers(user: User, tokens: ReturnType<typeof parse
 
 	const mentions = extractMentions(tokens);
 
-	let mentionedUsers = await Promise.all(mentions.map(m =>
+	let mentionedUsers = (await Promise.all(mentions.map(m =>
 		resolveUser(m.username, m.host || user.host).catch(() => null)
-	));
-
-	mentionedUsers = mentionedUsers.filter(x => x != null);
+	))).filter(x => x != null) as User[];
 
 	// Drop duplicate users
 	mentionedUsers = mentionedUsers.filter((u, i, self) =>
diff --git a/src/services/note/polls/update.ts b/src/services/note/polls/update.ts
index beb35cc278..277ace204d 100644
--- a/src/services/note/polls/update.ts
+++ b/src/services/note/polls/update.ts
@@ -7,8 +7,10 @@ import { Note } from '../../../models/entities/note';
 
 export async function deliverQuestionUpdate(noteId: Note['id']) {
 	const note = await Notes.findOne(noteId);
+	if (note == null) throw 'note not found';
 
 	const user = await Users.findOne(note.userId);
+	if (user == null) throw 'note not found';
 
 	const followers = await Followings.find({
 		followeeId: user.id
@@ -19,13 +21,8 @@ export async function deliverQuestionUpdate(noteId: Note['id']) {
 	// フォロワーがリモートユーザーかつ投稿者がローカルユーザーならUpdateを配信
 	if (Users.isLocalUser(user)) {
 		for (const following of followers) {
-			const follower = {
-				inbox: following.followerInbox,
-				sharedInbox: following.followerSharedInbox
-			};
-
-			if (following.followerHost !== null) {
-				const inbox = follower.sharedInbox || follower.inbox;
+			if (Followings.isRemoteFollower(following)) {
+				const inbox = following.followerSharedInbox || following.followerInbox;
 				if (!queue.includes(inbox)) queue.push(inbox);
 			}
 		}
diff --git a/src/services/note/polls/vote.ts b/src/services/note/polls/vote.ts
index 3051ff42d9..3bae617b4f 100644
--- a/src/services/note/polls/vote.ts
+++ b/src/services/note/polls/vote.ts
@@ -7,11 +7,13 @@ import { Not } from 'typeorm';
 import { genId } from '../../../misc/gen-id';
 import { createNotification } from '../../create-notification';
 
-export default (user: User, note: Note, choice: number) => new Promise(async (res, rej) => {
+export default async function(user: User, note: Note, choice: number) {
 	const poll = await Polls.findOne({ noteId: note.id });
 
+	if (poll == null) throw 'poll not found';
+
 	// Check whether is valid choice
-	if (poll.choices[choice] == null) return rej('invalid choice param');
+	if (poll.choices[choice] == null) throw new Error('invalid choice param');
 
 	// if already voted
 	const exist = await PollVotes.find({
@@ -21,10 +23,10 @@ export default (user: User, note: Note, choice: number) => new Promise(async (re
 
 	if (poll.multiple) {
 		if (exist.some(x => x.choice === choice)) {
-			return rej('already voted');
+			throw new Error('already voted');
 		}
 	} else if (exist.length !== 0) {
-		return rej('already voted');
+		throw new Error('already voted');
 	}
 
 	// Create vote
@@ -36,8 +38,6 @@ export default (user: User, note: Note, choice: number) => new Promise(async (re
 		choice: choice
 	});
 
-	res();
-
 	// Increment votes count
 	const index = choice + 1; // In SQL, array index is 1 based
 	await Polls.query(`UPDATE poll SET votes[${index}] = votes[${index}] + 1 WHERE noteId = '${poll.noteId}'`);
@@ -70,7 +70,7 @@ export default (user: User, note: Note, choice: number) => new Promise(async (re
 	const profile = await UserProfiles.findOne({ userId: user.id });
 
 	// ローカルユーザーが投票した場合この投稿をWatchする
-	if (Users.isLocalUser(user) && profile.autoWatch) {
+	if (Users.isLocalUser(user) && profile!.autoWatch) {
 		watch(user.id, note);
 	}
-});
+}
diff --git a/src/services/note/reaction/create.ts b/src/services/note/reaction/create.ts
index 55f9bcd084..ea2108430a 100644
--- a/src/services/note/reaction/create.ts
+++ b/src/services/note/reaction/create.ts
@@ -82,7 +82,7 @@ export default async (user: User, note: Note, reaction: string) => {
 	const profile = await UserProfiles.findOne({ userId: user.id });
 
 	// ユーザーがローカルユーザーかつ自動ウォッチ設定がオンならばこの投稿をWatchする
-	if (Users.isLocalUser(user) && profile.autoWatch) {
+	if (Users.isLocalUser(user) && profile!.autoWatch) {
 		watch(user.id, note);
 	}
 
@@ -91,7 +91,7 @@ export default async (user: User, note: Note, reaction: string) => {
 	if (Users.isLocalUser(user) && note.userHost !== null) {
 		const content = renderActivity(renderLike(user, note, reaction));
 		Users.findOne(note.userId).then(u => {
-			deliver(user, content, u.inbox);
+			deliver(user, content, u!.inbox);
 		});
 	}
 	//#endregion
diff --git a/src/services/note/reaction/delete.ts b/src/services/note/reaction/delete.ts
index 76f5ed631e..355e1c5466 100644
--- a/src/services/note/reaction/delete.ts
+++ b/src/services/note/reaction/delete.ts
@@ -42,7 +42,7 @@ export default async (user: User, note: Note) => {
 	if (Users.isLocalUser(user) && (note.userHost !== null)) {
 		const content = renderActivity(renderUndo(renderLike(user, note, exist.reaction), user));
 		Users.findOne(note.userId).then(u => {
-			deliver(user, content, u.inbox);
+			deliver(user, content, u!.inbox);
 		});
 	}
 	//#endregion
diff --git a/src/services/push-notification.ts b/src/services/push-notification.ts
index defd4d6e2d..1830cad623 100644
--- a/src/services/push-notification.ts
+++ b/src/services/push-notification.ts
@@ -1,26 +1,17 @@
 import * as push from 'web-push';
 import config from '../config';
 import { SwSubscriptions } from '../models';
-import { Meta } from '../models/entities/meta';
 import fetchMeta from '../misc/fetch-meta';
 
-let meta: Meta = null;
-
-setInterval(() => {
-	fetchMeta().then(m => {
-		meta = m;
-
-		if (meta.enableServiceWorker) {
-			// アプリケーションの連絡先と、サーバーサイドの鍵ペアの情報を登録
-			push.setVapidDetails(config.url,
-				meta.swPublicKey,
-				meta.swPrivateKey);
-		}
-	});
-}, 3000);
-
 export default async function(userId: string, type: string, body?: any) {
-	if (!meta.enableServiceWorker) return;
+	const meta = await fetchMeta();
+
+	if (!meta.enableServiceWorker || meta.swPublicKey == null || meta.swPrivateKey == null) return;
+
+	// アプリケーションの連絡先と、サーバーサイドの鍵ペアの情報を登録
+	push.setVapidDetails(config.url,
+		meta.swPublicKey,
+		meta.swPrivateKey);
 
 	// Fetch
 	const subscriptions = await SwSubscriptions.find({
diff --git a/src/services/register-or-fetch-instance-doc.ts b/src/services/register-or-fetch-instance-doc.ts
index 459f538e96..9957edd3db 100644
--- a/src/services/register-or-fetch-instance-doc.ts
+++ b/src/services/register-or-fetch-instance-doc.ts
@@ -5,8 +5,6 @@ import { genId } from '../misc/gen-id';
 import { toPuny } from '../misc/convert-host';
 
 export async function registerOrFetchInstanceDoc(host: string): Promise<Instance> {
-	if (host == null) return null;
-
 	host = toPuny(host);
 
 	const index = await Instances.findOne({ host });
diff --git a/src/services/stream.ts b/src/services/stream.ts
index c1d14b2779..c52af48b59 100644
--- a/src/services/stream.ts
+++ b/src/services/stream.ts
@@ -6,7 +6,7 @@ import { UserList } from '../models/entities/user-list';
 import { ReversiGame } from '../models/entities/games/reversi/game';
 
 class Publisher {
-	private ev: Xev;
+	private ev: Xev | null = null;
 
 	constructor() {
 		// Redisがインストールされてないときはプロセス間通信を使う
@@ -15,7 +15,7 @@ class Publisher {
 		}
 	}
 
-	private publish = (channel: string, type: string, value?: any): void => {
+	private publish = (channel: string, type: string | null, value?: any): void => {
 		const message = type == null ? value : value == null ?
 			{ type: type, body: null } :
 			{ type: type, body: value };
@@ -23,7 +23,7 @@ class Publisher {
 		if (this.ev) {
 			this.ev.emit(channel, message);
 		} else {
-			redis.publish('misskey', JSON.stringify({
+			redis!.publish('misskey', JSON.stringify({
 				channel: channel,
 				message: message
 			}));
diff --git a/src/tools/clean-remote-files.ts b/src/tools/clean-remote-files.ts
index f64affea97..e722552e14 100644
--- a/src/tools/clean-remote-files.ts
+++ b/src/tools/clean-remote-files.ts
@@ -3,6 +3,7 @@ import del from '../services/drive/delete-file';
 import { DriveFiles } from '../models';
 import { Not } from 'typeorm';
 import { DriveFile } from '../models/entities/drive-file';
+import { ensure } from '../prelude/ensure';
 
 const limit = promiseLimit(16);
 
@@ -17,7 +18,7 @@ DriveFiles.find({
 });
 
 async function job(file: DriveFile): Promise<any> {
-	file = await DriveFiles.findOne(file.id);
+	file = await DriveFiles.findOne(file.id).then(ensure);
 
 	await del(file, true);
 
diff --git a/src/tools/show-signin-history.ts b/src/tools/show-signin-history.ts
index 584bece6bb..9e6e849f5d 100644
--- a/src/tools/show-signin-history.ts
+++ b/src/tools/show-signin-history.ts
@@ -9,7 +9,7 @@ import { Users, Signins } from '../models';
 // node built/tools/show-signin-history username all
 //  with full request headers
 
-async function main(username: string, headers: string[]) {
+async function main(username: string, headers?: string[]) {
 	const user = await Users.findOne({
 		host: null,
 		usernameLower: username.toLowerCase(),
@@ -39,7 +39,7 @@ async function main(username: string, headers: string[]) {
 const args = process.argv.slice(2);
 
 let username = args[0];
-let headers: string[];
+let headers: string[] | undefined;
 
 if (args[1] != null) {
 	headers = args[1].split(/,/).map(header => header.toLowerCase());
diff --git a/tsconfig.json b/tsconfig.json
index 6bd8571207..4f1d1b9cd5 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -14,7 +14,8 @@
     "removeComments": false,
     "noLib": false,
     "strict": true,
-    "strictNullChecks": false,
+    "strictNullChecks": true,
+    "strictPropertyInitialization": false,
     "experimentalDecorators": true,
     "emitDecoratorMetadata": true,
     "resolveJsonModule": true,